# 📚 e-llm-studio/citation

## Table of Contents

1. [Project Overview](#project-overview)
2. [Installation](#installation)
3. [Available Components](#available-citations)
   - [Citation Components](#citation-components)
     - [BookCitation](#bookcitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/BookCitation/README.MD)
     - [ChatCitation](#chatcitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/ChatCitation/ChatCitationReadme.md)
     - [CitationRenderer](#citationrenderer) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/CitationRenderer/CitationRendererReadme.md)
     - [EmailCitation](#emailcitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/EmailCitation/EmailCitation.md)
     - [CognitiveDecisioningCard](#cognitivedecisioningcard) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/CognitiveDecisioning/CognitiveDecisioningReadme.md)
     - [CognitiveCompare](#cognitivecompare) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/new-compare-ui/citation/src/features/CognitiveCompare/README.md)
     - [CognitiveInternalGPTReasoning](#cognitiveinternalgptreasoning) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/CognitiveInternalgptReasoning/README.md)
     - [GptWebCitation](#gptwebcitation)
     - [CodeCitation](#codecitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/CodeCitation/README.md)
     - [ChatDrawer](#chatdrawer) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/ChatDrawer/ChatDrawerReadme.md)
     - [CitationsViewer](#citationsviewer) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/CitationViewer/CitationViewerReadme.md)
     - [PdfEditorCitation](#pdfeditorcitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/PdfEditorCitation/README.md)
     - [RequirementAICitation](#requirementaicitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/RequirementAiCitations/RequirementAiCitationsReadme.md)
     - [VideoCitationContent](#videocitationcontent) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/RequirementAiCitations/RequirementAiCitationsReadme.md)
     - [MarkdownWithImageCitation](#markdownwithimagecitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/MarkdownWithImageCitation/README.md)
     - [ScannedDocCitation](#scanneddoccitation) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/ScannedDocCitation/README.md)
     - [InstantLearningCitationComponent](#instantlearningcitationcomponent)
     - [CitationOrchestratorComponent](#citationorchestratorcomponent)
   - [Other Components](#other-components)
     - [Bookemon](#bookemon) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/Bookemon/BookemonReadme.md)
     - [DatagestMon](#datagestmon) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/DatagestMon/README.md)
     - [DataSelector](#dataselector)[<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/DataSelector/DataSelectorReadme.md)
     - [PaginatedTable](#paginatedtable) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/PaginatedTable/PaginatedTableReadme.md)
     - [PdfViewer](#pdfviewer) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/PdfViewer/PdfViewerReadme.md)
     - [ProjectAccordion](#projectaccordion) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/ProjectAccordion/README.md)
     - [UploadData](#uploaddata) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/UploadData/README.md)
     - [ReviewPanel](#reviewpanel) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/ReviewPanel/README.md)
     - [TableCitationContent](#tablecitationcontent) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/TableCitation/README.md)
     - [SplitterCitationsComponent](#splittercitationscomponent) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/SplitterCitations/README.md)
     - [RuleBookCitationWrapper](#RuleBookCitationWrapper) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/RuleBookCitations/README.md)
     -[ManageReminders](#ManageReminders) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/ManageRemainders/README.md)
     - [PromptemonBlockViewer](#promptemonblockviewer) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/PromptemonBlockViewer/PromptemonBlockViewerReadme.md)
     - [PromptemonViewer](#promptemonviewer) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/PromptemonViewer/PromptemonViewerReadme.md)
     - [SPBAnalysisPanel](#spbanalysispanel) [<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" width="18" height="18">](https://github.com/Techolution/e-llm-studio-lib/blob/dev/citation/src/features/SPBAnalysisPanel/SPBAnalysisPanel.md)
4. [Common Use Cases](#common-use-cases)
5. [Development & Contribution](#development--contribution)
6. [License](#license)

## Project Overview

The @e-llm-studio/citation library is a comprehensive React component library designed to render various types of citations and related UI elements within the e-LLM Studio ecosystem. It provides a robust set of reusable, production-ready components that enable developers to display citations, reasoning chains, code snippets, PDFs, and other content types with rich interactive features and highly customizable styling.

This library serves as a foundational building block for applications that need to present complex information in an organized, user-friendly manner. Whether you're displaying book citations with highlighted passages, rendering AI reasoning with confidence scores, showcasing code with syntax highlighting, or managing large datasets with pagination, the citation library offers flexible, well-documented components that integrate seamlessly into modern React applications.

The library emphasizes developer experience through comprehensive documentation, TypeScript support, and extensive customization options. Each component is designed with accessibility and performance in mind, ensuring that applications built with these components provide excellent user experiences across different devices and use cases.

---

## Installation

### Prerequisites

Before you begin, ensure you have the following installed on your system:

- **Node.js & npm** - Required for package management and running build scripts
- **Git** - Required for cloning the repository
- Basic familiarity with Git and the command line

### Installation Steps

#### 1. Clone the Repository

Start by cloning the citation library repository to your local machine:

```bash
git clone https://github.com/e-llm-studio/citation.git

cd citation
```

#### 2. Install Dependencies

Install all required dependencies using npm:

```bash
npm install
```

Alternatively, you can use yarn if you prefer:

```bash
yarn install
```

#### 3. Link the Library Locally (Optional)

If you want to test the library in another project before publishing, you can link it locally:

```bash
# In the citation library folder
npm link

# In your test project folder
cd ../your-project
npm link @e-llm-studio/citation
```

This allows you to test changes in your local library without publishing to npm.

#### 4. Build the Library

Build the library to compile TypeScript and prepare distribution files:

```bash
npm run build
```

#### 5. Test Locally

After building, you can test the library in your project:

```bash
# In your test project
npm start
# or
npm run build
```

Import the library components and verify that your changes work as expected.

### Quick Installation for End Users

If you're installing the published package from npm:

```bash
# Using npm
npm install @e-llm-studio/citation

# Using yarn
yarn add @e-llm-studio/citation

# Using pnpm
pnpm add @e-llm-studio/citation
```

---

# Citation Components

## BookCitation

### Overview

The BookCitation component is designed to display book citations with an interactive and expandable interface. It provides a rich, user-friendly way to present quoted text from books with support for highlighting, citation details management, and book cover images. The component enables readers to explore citations in context while maintaining a clean, organized presentation.

### Features

- **Text highlighting with partial and full match support** - Highlights specific text passages within citations using flexible matching algorithms
- **Automatic cleaning of scanned text to remove artifacts** - Intelligently removes OCR artifacts, page numbers, headers, and footers
- **Expandable/collapsible view of citation details** - Toggle between collapsed citation button and expanded view
- **Blur effect for non-highlighted text** - Applies visual blur to non-highlighted portions to focus reader attention
- **Scroll-to-highlight functionality** - Automatically scrolls to and centers highlighted text when expanded
- **Support for book cover images and external links** - Displays book cover images and provides clickable external links
- **Customizable styling through the customStyle prop** - Allows fine-grained control over component appearance


### Usage:

```tsx
import BookCitation from '@e-llm-studio/citation/BookCitation'

<BookCitation
 citationTitle="Sample Book"
 paragraphs={['<p>Highlighted text example</p>']}
 textToHighlight={['example']}
 partialMatch={true}
/>
```

### Props:

| Prop Name | Type | Description |
|-----------|------|-------------|
| `title` | `string` | Optional title of the book or publication being cited |
| `author` | `string \| string[]` | Optional author name(s) of the book or publication |
| `pageNumber` | `string` | Optional current page number where the citation is located |
| `totalPageNumber` | `string` | Optional total number of pages in the book or publication |
| `paragraphs` | `string[]` | Required array of HTML strings containing the text content |
| `citationTitle` | `string` | Required title or label for the citation |
| `textToHighlight` | `string[]` | Required array of text strings to highlight within the paragraphs |
| `bookCoverImage` | `string` | Optional URL or path to the book cover image |
| `handleExternalLinkClick` | `() => void` | Optional callback function triggered when external link is clicked |
| `externalLinkComponent` | `React.ReactNode` | Optional React component to render as an external link button |
| `citationNumber` | `number` | Optional citation number displayed in the citation button |
| `partialMatch` | `boolean` | Optional flag to enable partial text matching when highlighting |
| `defaultState` | `boolean` | Optional flag to set the initial expanded/collapsed state |
| `isNonHighlightedBlur` | `boolean` | Optional flag to enable blur effect on non-highlighted text |
| `customStyle` | `object` | Optional object for overriding default styles |
| `useDropdown` | `boolean` | Optional flag to render the citation as a dropdown (default: `true`) |

---
---
 
### CognitiveCompare (Main Component)

A side-by-side document comparison component with cognitive analysis, deviation badges, citation-linked PDF previews, and two layout modes (Standard and Relative Order). For full documentation see the [dedicated README](https://github.com/Techolution/e-llm-studio-lib/blob/new-compare-ui/citation/src/features/CognitiveCompare/README.md).

### Props

| Prop                  | Type                                | Default                 | Description                                                                                                                                                                 |
| --------------------- | ----------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `treeData`            | `Record<string, any> \| null`       | —                       | **Required.** Backend tree structure powering both columns.                                                                                                                 |
| `displayConfig`       | [`IDisplayConfig`](#idisplayconfig) | —                       | **Required.** Controls header/toggle visibility and initial layout mode.                                                                                                    |
| `componentHeaderText` | `string`                            | `"Contract Comparison"` | Text shown in the top header bar.                                                                                                                                           |
| `deviationData`       | `Record<string, any>`               | `{}`                    | Per-node deviation analysis results keyed by node ID. Populates the Deviation Analysis tab in the cognitive popup and drives inline text highlights within section content. |

---

#### IDisplayConfig

| Property                | Type      | Default | Description                                                            |
| ----------------------- | --------- | ------- | ---------------------------------------------------------------------- |
| `isHeaderVisible`       | `boolean` | `true`  | Show or hide the top header bar.                                       |
| `isToggleVisible`       | `boolean` | `true`  | Show or hide the Standard / Relative Order toggle switch.              |
| `maintainRelativeOrder` | `boolean` | `false` | Initial layout mode — `true` for Relative Order, `false` for Standard. |

---

### treeData Shape

`treeData` is the primary data contract. It must be a flat object where every key is a node ID, plus four reserved keys.

```ts
{
  // Top-level metadata keys
  base_root_id: string,           // ID of the root node (looked up inside nodes)
  input_index_map: {              // Maps side index to document UUID
    "0": string,                  // left side UUID
    "1": string,                  // right side UUID
  },
  documents: {                    // Document metadata keyed by UUID
    [uuid: string]: {
      title: string,
      signed_url: string,         // PDF URL used by CitationAnchor / PdfViewer
    }
  },

  // All node data lives under the `nodes` key
  nodes: {
    // Root node (identified by base_root_id)
    [rootId: string]: {
      display_node?: boolean,
      comparison_inputs: {
        [uuid: string]: { title: string }   // column titles
      },
      decision_scope_description?: string,
      next?: Record<string, string>,         // child node IDs
    },

    // Section nodes
    [nodeId: string]: {
      display_node?: boolean,        // set false to hide the node
      evaluation_result?: DeviationDataEntry, // deviation result attached directly to node
      comparison_inputs: {
        [uuid: string]: {
          title: string,
          content: string,
          additional_attributes?: {
            display_index?: number,    // used in Relative Order mode for sorting
            display_title?: boolean,   // set false to suppress rendering the title
            display_content?: boolean, // set false to suppress rendering the content
          }
        }
      },
      next?: Record<string, string>, // child node IDs (for subsections)
      mapping_rationale?: {
        decision_strength?: string,  // numeric string, e.g. "72"
        decisioning_factors?: string[],
        gaps_in_decision?: string[],
        citations?: Record<string, Record<string, CitationEntry>>
      }
    }
  }
}
```

> All node data (root and section nodes) lives under the `nodes` key. The top-level `base_root_id`, `input_index_map`, and `documents` keys remain directly on `treeData`.

#### deviationData Shape

```ts
// deviationData[nodeId]
{
  evaluation_outputs?: {
    output_value?: string,           // badge label text
    metadata?: { label_color?: string } // hex — drives badge/highlight colors
  },
  cognitive_decisioning?: {
    decisioning_factors?: string[],
    gaps_in_decision?: string[],
    citations?: Record<string, any>,
    decision_strength?: string | null,
  },
  deviations?: Record<string, any>,  // { devKey: { [docUuid]: highlightText } }
}
```

#### Usage

```tsx
import CognitiveCompare from "@e-llm-studio/citation/CognitiveCompare";

<CognitiveCompare
  treeData={myTreeData}
  displayConfig={{
    isHeaderVisible: true,
    isToggleVisible: true,
    maintainRelativeOrder: false,
  }}
  deviationData={myDeviationData}
/>;
```

#### Key Behaviours

- Badge and highlight colors are generated dynamically from `evaluation_outputs.metadata.label_color` via `generateColorPalette()`. The static `relationStyles` map has been removed.
- Clicking a badge in **Standard mode** opens `CognitivePopup` directly. In **Relative Order mode** it opens `MoreFunctionsPopup` offering Connect, Side by Side, and Cognitive Decisioning actions.
- The **Deviation Analysis** tab is shown first in the popup and displays `cognitive_decisioning.decisioning_factors` and `gaps_in_decision` with inline citation anchors that open split PDF viewers.
- `deviations` entries drive inline `<mark>` highlights inside section content, colored using the same `label_color`-derived palette.

---

## ChatCitation

### Overview

ChatCitation is a composable React UI component for rendering chat-based citations, including summarized and detailed chat views alongside a rule book/reference section. The component is designed to be highly customizable via renderers, slot styles, and slot props, making it flexible for various use cases.

### Features

- **Composable chat views** - Supports both summarized and detailed chat display modes
- **Rule book/reference section** - Optional left panel for displaying supporting rules and references
- **Markdown rendering** - Rich text support with customizable markdown renderers
- **Customizable styling** - Fine-grained control over styles through slot-based customization
- **Relevance scoring** - Display AI relevance scores for citations
- **Tab-based navigation** - Toggle between summarized and detailed views
- **Flexible content rendering** - Support for custom renderers and markdown components

### Usage

```tsx
import ChatCitation from '@e-llm-studio/citation/ChatCitation'

<ChatCitation
 chatContainer={{
 chatData: [
 { role: 'user', message: 'Hello', userName: 'User1', timeStamp: dayjs() }
 ]
 }}
 ruleBookContainer={{
 title: 'References',
 data: { content: 'Rule content', highlighted_texts: ['important'] }
 }}
/>
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `rootContainer` | `RootContainerProps` | Optional top-level container configuration |
| `chatContainer` | `ChatContainerProps` | Required chat container configuration with chat data |
| `ruleBookContainer` | `RuleBookContainerProps` | Optional rule book/reference section configuration |
| `renderer` | `FeatureModMarkdownProps["renderers"]` | Optional custom markdown renderers |

---


## ChatDrawer

### Overview

ChatDrawer is a generic, resizable drawer component for rendering collapsible panels with a draggable resize handle. All content is consumer-owned — pass any React node as `children`: forms, file lists, summary cards, tables, or any custom component. The consuming team is fully responsible for styling and rendering the content inside.

### Features

- **Collapsible panel** — Header is always visible; body and drag handle only render when open
- **Notch toggle** — Small tab below the drawer with a chevron arrow; click to expand/collapse, drag to resize
- **Drag to resize** — Grab the pill handle at the bottom to resize between `minHeight` and `maxHeight`
- **Configurable height** — `defaultHeight`, `minHeight`, `maxHeight` all exposed as props
- **Consumer-owned content** — Zero opinion on what goes inside, pass any React node
- **Deep style overrides** — Every visual region customizable via the `styles` prop
- **Inline styles only** — No Tailwind or MUI dependency, works in any consuming app

### Usage

```tsx
import ChatDrawer from '@e-llm-studio/citation/ChatDrawer'

<ChatDrawer
  uploadListTopContent="My Panel"
  isExpanded={isOpen}
  onToggle={() => setIsOpen(v => !v)}
  defaultHeight={300}
  minHeight={150}
  maxHeight="60vh"
>
  {/* Pass any component here — form, file list, summary cards, etc. */}
  <YourComponent />
</ChatDrawer>
```

**With onHeightChange (sibling layout adjustment):**
```tsx
const [drawerHeight, setDrawerHeight] = useState(300);

<ChatDrawer
  uploadListTopContent="Context"
  isExpanded={isOpen}
  onToggle={() => setIsOpen(v => !v)}
  defaultHeight={300}
  onHeightChange={setDrawerHeight}
>
  <YourComponent />
</ChatDrawer>
```


### With drawer summary
```tsx
<ChatDrawer
  uploadListTopContent="Custom Notch"
  isExpanded={isOpen}
  onToggle={() => setIsOpen(v => !v)}
  styles={{
    notch: { backgroundColor: '#6d28d9', border: '1px solid #5b21b6' },
    notchArrowColor: '#fff',
  }}
  drawerSummaryComponent={<RedliningFixesSummaryUI approved={5} rejected={2} pending={3} />}
>
  <YourComponent />
</ChatDrawer>
```

### With drawer countBadge
```tsx
<ChatDrawer
  uploadListTopContent="Custom Notch"
  isExpanded={isOpen}
  onToggle={() => setIsOpen(v => !v)}
  styles={{
    notch: { backgroundColor: '#6d28d9', border: '1px solid #5b21b6' },
    notchArrowColor: '#fff',
  }}
  totalCountsBadge={<TotalCountsBadge totalDeviations={10} resolvedDeviations={7} />}
>
  <YourComponent />
</ChatDrawer>
```

### With drawer header component prop
```tsx
<ChatDrawer
  uploadListTopContent="Custom Notch"
  isExpanded={isOpen}
  onToggle={() => setIsOpen(v => !v)}
  styles={{
    notch: { backgroundColor: '#6d28d9', border: '1px solid #5b21b6' },
    notchArrowColor: '#fff',
  }}
  headerComponent={<AutopilotIndicator />}
>
  <YourComponent />
</ChatDrawer>
```

**With styles (theme customization):**
```tsx
<ChatDrawer
  uploadListTopContent="Dark Panel"
  isExpanded={isOpen}
  onToggle={() => setIsOpen(v => !v)}
  styles={{
    container: { backgroundColor: '#1a1a2e', border: '1px solid #444' },
    header: { backgroundColor: '#1a1a2e' },
    title: { color: '#fff' },
    body: { backgroundColor: '#1a1a2e' },
    notch: { backgroundColor: '#1a1a2e', border: '1px solid #444' },
    notchArrowColor: '#fff',
  }}
>
  <YourComponent />
</ChatDrawer>
```

### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `children` | `ReactNode` | ❌ | Scrollable body — fully consumer owned. Pass any React node. |
| `uploadListTopContent` | `string` | ❌ | Header title shown in the always-visible top bar. Defaults to `"Data uploaded for your context"`. |
| `isExpanded` | `boolean` | ❌ | Controlled open/close state. Defaults to `false`. |
| `onToggle` | `() => void` | ❌ | Called when the notch is clicked. Wire your open/close state here. |
| `defaultHeight` | `number` | ❌ | Initial height of the panel in px when expanded. Defaults to `300`. |
| `minHeight` | `number` | ❌ | Minimum height in px when drag-resizing. Defaults to `150`. |
| `maxHeight` | `number \| string` | ❌ | Maximum height when drag-resizing. Accepts a px number or a CSS string like `"70vh"`. Defaults to `40vh`. |
| `onHeightChange` | `(height: number) => void` | ❌ | Fired on every drag tick with the current height in px. Useful when a sibling layout needs to react to height changes. |
| `styles` | `ChatDrawerStyles` | ❌ | Style overrides for each visual region. Keys: `container`, `header`, `title`, `body`, `dragPill`, `notch`, `notchArrowColor`. Each accepts any valid `CSSProperties` except `notchArrowColor` which is a `string`. |

---

## CitationRenderer

### Overview

CitationRenderer is a versatile, interactive "Pill" component designed to display a compact reference citation that expands into detailed content. It provides a space-efficient toggle mechanism, perfect for displaying source material, footnotes, or reasoning chains without cluttering the main UI. It works seamlessly with MarkdownRenderer to display rich, interactive text content.

### Features

- **Expandable pill button** - Compact display that expands on click
- **Customizable icons** - Support for custom icons for chevron and citation indicators
- **Markdown content support** - Render rich text content using MarkdownRenderer
- **Controlled and uncontrolled modes** - Manage state internally or externally
- **Flexible styling** - Customize appearance through style props
- **Callback support** - Optional callbacks for side effects on toggle

### Usage

```tsx
import CitationRenderer from '@e-llm-studio/citation/CitationRenderer'

<CitationRenderer
 inLineCitation={true}
 citationTitle="Reference 1"
 citationComponent={<div>Detailed content here</div>}
 chevronDownComponent={<ChevronDownIcon />}
 chevronUpComponent={<ChevronUpIcon />}
/>
```

### Props 

| Prop Name | Type | Description |
|-----------|------|-------------|
| `inLineCitation` | `boolean` | Must be true to enable expand/collapse behavior |
| `citationTitle` | `string` | The text displayed inside the pill button |
| `citationComponent` | `ReactNode` | The content to render when expanded |
| `citationIcon` | `ReactNode` | Icon displayed to the left of the title |
| `chevronUpComponent` | `ReactNode` | Icon shown when the citation is expanded |
| `chevronDownComponent` | `ReactNode` | Icon shown when the citation is collapsed |
| `additionalCallbackForPillButton` | `func` | Hook to trigger side effects on click |
| `styles` | `Object` | CSS overrides for styling |
| `isOpen` | `boolean` | Forces the expanded state (controlled mode) |
| `onToggle` | `func` | Callback fired when the pill is clicked |

---


## CognitiveDecisioningCard

### Overview

CognitiveDecisioningCard is a specialized React UI component designed to provide transparency into AI workflows. It renders a toggleable "Pill" that expands into a detailed card, displaying the AI's Reasoning, identified Gaps, and a confidence Score. It features a nested accordion design, robust Markdown rendering for content, and full styling customization.


### Features

- **Toggleable pill button** - Click to expand/collapse the detailed card
- **Reasoning and gap sections** - Display AI reasoning and identified gaps with markdown support
- **Confidence score badge** - Show confidence percentage in the header
- **Nested accordion design** - Collapsible sections for organized content
- **Custom markdown rendering** - Support for custom markdown components
- **Icon customization** - Replace default icons with custom components
- **Advanced section customization** - Override default sections with custom data structures

### Usage

```tsx
import CognitiveDecisioningCard from '@e-llm-studio/citation/CognitiveDecisioningCard'

<CognitiveDecisioningCard
 isOpen={isOpen}
 onToggle={() => setIsOpen(!isOpen)}
 score="92"
 reasoning="**Analysis:** Based on document review..."
 gap="Missing date information in section 3."
 title="AI Analysis Report"
/>
```

**Advanced Customization**:
```tsx
const customSections = [
 {
 id: 'step1',
 title: 'Data Retrieval',
 subtitle: '3 sources processed',
 icon: <CheckIcon />,
 content: 'Data retrieved successfully'
 }
]

<CognitiveDecisioningCard
 isOpen={true}
 sections={customSections}
 score="100"
 mdComponents={{
 a: ({ node, ...props }) => <a {...props} target="_blank" />
 }}
/>
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `reasoning` | `string` | Markdown text explaining the AI's logic |
| `gap` | `string` | Markdown text explaining missing info or uncertainties |
| `score` | `string` | Confidence score percentage (e.g., "92") |
| `isOpen` | `boolean` | Controls the visibility of the expanded card |
| `onToggle` | `() => void` | Callback handler for the pill trigger click |
| `title` | `string` | Header title. Default: "Cognitive Decisioning AI" |
| `hideTrigger` | `boolean` | If true, hides the pill button |
| `sections` | `SectionContent[]` | Advanced: Overrides default Reasoning/Gap sections |
| `mdComponents` | `Object` | Custom renderers for react-markdown |
| `headerIcon` | `ReactNode` | Replaces the default brain icon |
| `reasoningIcon` | `ReactNode` | Replaces the icon for the reasoning section |
| `gapIcon` | `ReactNode` | Replaces the icon for the gap section |
| `scoreIcon` | `ReactNode` | Replaces the sparkle icon in the score badge |
| `reasoningTitle` | `string` | Title for the reasoning section. Default: "Decision Making Factors" |
| `reasoningSubtitle` | `string` | Subtitle for the reasoning section. Default: "Why this was picked" |
| `gapTitle` | `string` | Title for the gap section. Default: "Gaps in Decision" |
| `gapSubtitle` | `string` | Subtitle for the gap section. Default: "What's missing or unclear" |
| `scoreLabel` | `string` | Label prefix shown before the score percentage. Default: "Decision Strength: " |

---

## CognitiveInternalGPTReasoning

### Overview

The CognitiveInternalgptReasoningComponent is a React component designed to render non-web search reasoning citations with advanced interactive features. It provides a comprehensive display of reasoning data with support for expandable content, highlight navigation, and modal fullscreen viewing. This component is particularly useful for displaying AI-generated reasoning, training data citations, and confidence scores in a user-friendly format.

### Features

- **Expandable Content** - Display a paraphrase text that expands to show the full data source content
- **Highlight Navigation** - Automatically extract and navigate between highlighted sections within the content
- **Confidence Score Display** - Show confidence percentage in both expanded view and modal
- **Fullscreen Modal View** - Open a fullscreen modal for detailed examination of reasoning data
- **Text Formatting Support** - Handle bold text, list items, headers, and special highlight tags
- **Custom Icon Support** - Replace default icons with custom React components
- **Theming Support** - Customize component appearance using `themeTokens`, `classNames`, and `styles`

### Usage

```tsx
import NonWebReasoningComponent from '@e-llm-studio/citation/CognitiveInternalgptReasoningComponent'

const reasoningData = {
 text: "Reasoning text here",
 dataSource: "Source with <highlight>highlighted text</highlight>",
 confidence_score: 95,
 paraphrase: "Brief summary",
 previewCallback?:callback
 DocumentTitle?: "title";
}

<NonWebReasoningComponent
 item={reasoningData}
 index={1}
 headerTitle="GPT Reasoning"
/>
```

**Highlight Navigation**:
- Extracts `<highlight>` tags from dataSource
- Provides navigation between highlighted sections
- Shows current position (e.g., "2/5 highlights")
- Auto-scrolls to active highlight
- previewCallback we can use this to pass a callback for external link opening or pdf opening
- DocumentTitle : pdf title or document title
- `themeTokens` can be used to pass CSS variable based theming
- `classNames` can be used to override classes for individual sections
- `styles` can be used to pass inline style overrides for individual sections

### Additional Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `themeTokens` | `CognitiveReasoningThemeTokens` | `undefined` | Optional CSS variable based theme tokens |
| `classNames` | `CognitiveReasoningClassNames` | `undefined` | Optional class overrides for individual sections |
| `styles` | `CognitiveReasoningStyles` | `undefined` | Optional inline style overrides for individual sections |

---

## GptWebCitation

### Overview

`GptWebCitation` is a composite React component that wraps the GPT reasoning citation (`CognitiveInternalgptCoreComponent`) and adds an optional **Web Citation** view. Users can toggle between GPT and web-based citations without modifying the underlying GPT citation code.

In **GPT view**, the component renders the standard GPT citation panel with a **View Web Citation** button on the left and the document source link on the right (inside the GPT citation footer). In **Web Citation view**, it shows a screenshot snapshot of the source page (when available), a relevance score badge, visit links, and a **View GPT Citation** toggle to switch back.

The component is **presentational** — it does not fetch web citations. The parent owns `webCitationData`, `webCitationStatus`, and view toggling via the required `citationType` prop.

### `CitationType`

Import from `@e-llm-studio/citation`:

```tsx
import { CitationType } from '@e-llm-studio/citation';
```

| Value | GPT view | Web view | Toggle | Default view |
| --- | --- | --- | --- | --- |
| `CitationType.GPT` | yes | no | no | GPT only |
| `CitationType.WEB` | no | yes | no | Web only |
| `CitationType.GPT_WEB` | yes | yes | yes | Web (uncontrolled) |

`citationType` is **required**. Use `CitationType.GPT_WEB` when users should switch between GPT reasoning and web screenshot citations.

### Features

- **Dual citation views** — Toggle between GPT reasoning and web-based citation
- **Non-invasive GPT integration** — Wraps `CognitiveInternalgptCoreComponent` via props; no changes to GPT citation code required
- **Screenshot web citations** — Renders `imageMetadata.signed_url` when the API returns a snapshot
- **Status-driven skeleton UI** — `"pending"` loading skeleton and `"error"` fallback with **Visit Link**
- **`defaultCitationUrl`** — Immediate visit link while fetch is in progress (before `highlightedUrl` arrives)
- **Visit link priority** — `highlightedUrl` from API response wins over `defaultCitationUrl` in pending/error states
- **Relevance score badge** — Auto-extracted from web citation content (e.g. "decision strength is 85%")
- **Expand screenshot button** — Optional full-screen image view (`showExpandImageButton`)
- **Custom icons** — Override expand and external-link icons via `iconsConfig`
- **Fixed height mode** — Optional `isFixedHeight` keeps GPT and web panels the same size with contained screenshots
- **Style overrides** — Customize layout via the `styles` prop without editing component internals

### Installation / Import

```tsx
import GptWebCitation from '@e-llm-studio/citation/GptWebCitation';

// Optional utilities and types
import {
  mapCitationDataToDisplay,
  getWebCitationImageUrl,
  resolveSkeletonVisitUrl,
  type GptWebCitationStatus,
  type IWebCitationApiResponse,
  type IGptWebCitationStyleOverrides,
  type IGptWebCitationImageStyles,
  type IGptWebCitationSkeletonStyles,
  type IGptWebCitationVisitLinkStyles,
  type IGptWebCitationFullScreenStyles,
  CitationType,
} from '@e-llm-studio/citation';
```

### Usage 1: Basic GPT + Web Citation Toggle

```tsx
import { useState } from 'react';
import { ChevronDown, ChevronUp, ExternalLink, Maximize2, X } from 'lucide-react';
import GptWebCitation from '@e-llm-studio/citation/GptWebCitation';
import { CitationType, type GptWebCitationStatus } from '@e-llm-studio/citation';

const gptCitation = {
  item: {
    confidence_score: 100,
    text: 'Standard financial data interpretation patterns.',
    dataSource:
      'Title: Commodity Market Analysis\n\n- <highlight>Verify the most recent timestamp in search results.</highlight>\n- Analyze safe-haven asset demand and geopolitical triggers.',
    paraphrase: 'Market interpretation patterns for commodity price reporting.',
  },
  headerTitle: 'Summary Citations',
  index: 0,
  iconsConfig: {
    ChevronDownIcon: ChevronDown,
    ChevronUpIcon: ChevronUp,
    MaximizeIcon: Maximize2,
    CloseIcon: X,
  },
  DocumentTitle: 'Source : Employee Handbook - Code of Conduct Section.pdf',
  previewCallback: () => window.open('/preview/document'),
};

const webCitationIcons = {
  MaximizeIcon: Maximize2,
  ExternalLinkIcon: ExternalLink,
};

function CitationPanel() {
  const [showWebCitation, setShowWebCitation] = useState(false);
  const [webCitationData, setWebCitationData] = useState(undefined);
  const [webCitationStatus, setWebCitationStatus] =
    useState<GptWebCitationStatus>('pending');

  const handleGenerateWebCitation = async () => {
    setShowWebCitation(true);
    setWebCitationStatus('pending');

    try {
      const response = await fetch('/api/web-citation/generate');
      const data = await response.json();
      setWebCitationData(data);
      setWebCitationStatus('success');
    } catch {
      setWebCitationStatus('error');
    }
  };

  return (
    <GptWebCitation
      gptCitation={gptCitation}
      defaultCitationUrl="https://example.com/article"
      citationType={CitationType.GPT_WEB}
      webCitationData={webCitationData}
      webCitationStatus={webCitationStatus}
      showWebCitation={showWebCitation}
      onGenerateWebCitation={handleGenerateWebCitation}
      onToggleCitationView={() => setShowWebCitation((prev) => !prev)}
      iconsConfig={webCitationIcons}
    />
  );
}
```

### Usage 2: Web Citation API Response Shape

Pass the API response from your web citation service as `webCitationData`:

```tsx
const webCitationData = {
  citationId: '550e8400-e29b-41d4-a716-446655440061',
  content:
    'The decision strength is 85% because:<ol><li>The exact <a href="https://example.com/article">valuation of SpaceX</a> fluctuates between sources.</li></ol>',
  citationType: 'web',
  citationUrl: 'https://example.com/article',
  highlightedUrl: 'https://example.com/article#highlight',
  message: 'Citation processed successfully',
  imageMetadata: {
    signed_url: 'https://storage.example.com/image_citations/screenshot.png',
    blob_path: 'image_citations/screenshot.png',
    gs_uri: 'gs://bucket/image_citations/screenshot.png',
  },
};

<GptWebCitation
  gptCitation={gptCitation}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT_WEB}
  webCitationData={webCitationData}
  webCitationStatus="success"
  showWebCitation={true}
/>
```

When `imageMetadata.signed_url` is present and `webCitationStatus` is `"success"`, the component renders a screenshot snapshot. If the image is unavailable or the fetch fails, an error skeleton is shown with a **Visit Link** (using `highlightedUrl` or `defaultCitationUrl`).

#### Visit link resolution

| UI state | Visit link source |
| --- | --- |
| Pending / error skeleton | `highlightedUrl` from `webCitationData` → else `defaultCitationUrl` prop |
| Screenshot footer (success) | `citationUrl` from `webCitationData` |

Use `resolveSkeletonVisitUrl(highlightedUrl, defaultCitationUrl)` from `@e-llm-studio/citation` if you need the same logic outside the component.

### Usage 3: GPT-Only Mode (No Web Citation)

Set `citationType={CitationType.GPT}` to render only the GPT citation with no toggle button. `defaultCitationUrl` is still required by the prop contract but is unused in GPT-only mode:

```tsx
<GptWebCitation
  gptCitation={gptCitation}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT}
/>
```

### Usage 3b: Web-Only Mode (No GPT Citation)

Set `citationType={CitationType.WEB}` to render only the web citation panel with no toggle:

```tsx
<GptWebCitation
  gptCitation={gptCitation}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.WEB}
  webCitationData={webCitationData}
  webCitationStatus="success"
/>
```

### Usage 4: Hide Expand Buttons

Hide the web citation screenshot expand button:

```tsx
<GptWebCitation
  gptCitation={gptCitation}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT_WEB}
  webCitationData={webCitationData}
  webCitationStatus="success"
  showWebCitation={true}
  showExpandImageButton={false}
/>
```

Hide the GPT citation header maximize/expand icon:

```tsx
<GptWebCitation
  gptCitation={gptCitation}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT_WEB}
  showGptMaximizeButton={false}
/>
```

You can also use `gptCitation.disableMaximize: true` directly on the GPT config.

### Usage 5: Custom Styling via Props (matched heights)

Layout, borders, and heights for **both GPT and web views** can be controlled from the parent without modifying component internals. Prefer **`isFixedHeight`** (Usage 6) when you only need equal panel size + contained screenshots; use `styles` when you need granular control over skeleton, image, visit-link, or full-screen elements:

```tsx
const sharedPanelHeight = '520px';
const sharedContentHeight = '384px';

<GptWebCitation
  gptCitation={{
    ...gptCitation,
    bodyHeight: sharedContentHeight,
  }}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT_WEB}
  webCitationData={webCitationData}
  webCitationStatus="success"
  showGptMaximizeButton={true}
  iconsConfig={{
    MaximizeIcon: Maximize2,
    ExternalLinkIcon: ExternalLink,
  }}
  styles={{
    container: { maxWidth: 900 },
    gptCitation: {
      wrapper: {
        minHeight: sharedPanelHeight,
        border: '1px solid #e5e7eb',
        borderRadius: 8,
      },
      footerAction: { left: '1.5rem' },
      toggleButton: { minWidth: 180, fontSize: 14 },
    },
    webCitation: {
      panel: {
        minHeight: sharedPanelHeight,
        border: '1px solid #e5e7eb',
        borderRadius: 8,
      },
      header: { padding: '8px 16px' },
      content: {
        minHeight: sharedContentHeight,
        maxHeight: sharedContentHeight,
        overflowY: 'auto',
      },
      footer: { padding: '8px 16px' },
      toggleButton: { minWidth: 180, fontSize: 14 },
      learnedFrom: { fontSize: 13 },
    },
  }}
/>
```

#### Style keys

| Key | Applies to | Description |
|-----|------------|-------------|
| `container` | Both views | Shared outer wrapper (`overlay` in GPT view, merged into web `panel`) |
| `gptCitation.wrapper` | GPT view | Border card around GPT citation (left/right borders restored here) |
| `gptCitation.footerAction` | GPT view | View Web Citation button row in footer |
| `gptCitation.toggleButton` | GPT view | View Web Citation button styles |
| `webCitation.panel` | Web view | Outer web citation card |
| `webCitation.header` | Web view | Source label + relevance score badge row |
| `webCitation.content` | Web view | Screenshot or loading/error skeleton |
| `webCitation.footer` | Web view | View GPT Citation + Learned From row |
| `webCitation.toggleButton` | Web view | View GPT Citation button styles |
| `webCitation.learnedFrom` | Web view | "Learned From …" text styles |
| `webCitation.visitLink.row` | Image + skeleton | Shared visit link row (merged with scoped overrides below) |
| `webCitation.visitLink.hint` | Image + skeleton | Shared visit link hint text |
| `webCitation.visitLink.link` | Image + skeleton | Shared visit link anchor styles |
| `webCitation.image.wrapper` | Screenshot view | Outer image citation wrapper |
| `webCitation.image.center` | Screenshot view | Center column (viewport or inline skeleton) |
| `webCitation.image.viewport` | Screenshot view | Viewport around scroll container |
| `webCitation.image.scrollContainer` | Screenshot view | Scrollable screenshot container |
| `webCitation.image.image` | Screenshot view | Screenshot `<img>` element |
| `webCitation.image.expandButton` | Screenshot view | Full-screen expand button |
| `webCitation.image.visitLink.*` | Screenshot footer | Image-specific visit link overrides (merged on top of `webCitation.visitLink`) |
| `webCitation.image.fullScreen.overlay` | Full-screen viewer | Portal overlay backdrop |
| `webCitation.image.fullScreen.content` | Full-screen viewer | Modal content card |
| `webCitation.image.fullScreen.closeButton` | Full-screen viewer | Close button |
| `webCitation.image.fullScreen.imageWrapper` | Full-screen viewer | Scrollable image wrapper |
| `webCitation.image.fullScreen.image` | Full-screen viewer | Full-screen `<img>` |
| `webCitation.skeleton.container` | Pending/error | Outer skeleton column |
| `webCitation.skeleton.frame` | Pending/error | Gray skeleton frame |
| `webCitation.skeleton.shimmer` | Pending | Shimmer animation overlay |
| `webCitation.skeleton.pending.content` | Pending | Centered pending content block |
| `webCitation.skeleton.pending.text` | Pending | Loading message text |
| `webCitation.skeleton.pending.actionRow` | Pending | Visit link row |
| `webCitation.skeleton.pending.actionHint` | Pending | "to view details" hint |
| `webCitation.skeleton.error.content` | Error | Error content block |
| `webCitation.skeleton.error.title` | Error | "No preview available" title |
| `webCitation.skeleton.error.message` | Error | Restriction message |
| `webCitation.skeleton.error.actionGroup` | Error | Action row wrapper |
| `webCitation.skeleton.error.detailsToggle` | Error | Error details expand button |
| `webCitation.skeleton.error.detailsMessage` | Error | Expanded error details text |
| `webCitation.skeleton.error.visitLinkGlow` | Error | Glowing visit link (merged on top of visit link styles) |
| `webCitation.skeleton.visitLink.*` | Pending/error | Skeleton-specific visit link overrides (merged on top of `webCitation.visitLink`) |

Legacy flat keys (`gptCitationWrapper`, `footerAction`, `webCitationButton`) still work for backward compatibility.

#### Example: customize screenshot and pending skeleton

```tsx
<GptWebCitation
  gptCitation={gptCitation}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT_WEB}
  webCitationData={data}
  webCitationStatus={status}
  styles={{
    webCitation: {
      visitLink: {
        link: { backgroundColor: 'rgba(37, 99, 235, 0.08)', borderRadius: 8 },
      },
      image: {
        scrollContainer: { borderRadius: 16, borderColor: '#d1d5db' },
        image: { objectFit: 'contain', maxHeight: 360 },
        expandButton: { backgroundColor: '#111827' },
      },
      skeleton: {
        frame: { minHeight: 320, backgroundColor: '#f8fafc' },
        pending: {
          text: { fontSize: 14, color: '#374151' },
        },
        error: {
          title: { color: '#dc2626' },
          visitLinkGlow: { borderColor: '#dc2626' },
        },
      },
    },
  }}
/>
```

### Usage 6: Fixed height mode (matched GPT + web panels)

Set `isFixedHeight={true}` when you want GPT and web citation views to share the same panel dimensions. Screenshots use `object-fit: contain` so tall pages stay inside the box without layout shift when toggling views.

```tsx
<GptWebCitation
  gptCitation={{
    ...gptCitation,
    bodyHeight: '384px', // optional — customizes inner content height
  }}
  defaultCitationUrl="https://example.com/article"
  citationType={CitationType.GPT_WEB}
  isFixedHeight
  webCitationData={webCitationData}
  webCitationStatus="success"
  showWebCitation={showWebCitation}
  onToggleCitationView={() => setShowWeb((v) => !v)}
/>
```

| Scenario | Panel height |
| --- | --- |
| `isFixedHeight` + `CitationType.GPT_WEB` (toggle footer present) | `520px` default, or `calc(bodyHeight + 3.25rem)` when `gptCitation.bodyHeight` is set |
| `isFixedHeight` + `CitationType.GPT` or `CitationType.WEB` | `520px` default, or `gptCitation.bodyHeight` when set |

`isFixedHeight` applies flex layout and contained images automatically. For manual per-element styling without fixed dimensions, use `styles` (Usage 5) instead.

### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `gptCitation` | `IGptCitationConfig` | **required** | GPT citation config passed to `CognitiveInternalgptCoreComponent` |
| `defaultCitationUrl` | `string` | **required** | Fallback source URL for **Visit Link** in pending/error skeletons. Used when `webCitationData.highlightedUrl` is not yet available |
| `citationType` | `CitationType` | **required** | `GPT` = GPT only, `WEB` = web only, `GPT_WEB` = both views with toggle (default web view when uncontrolled) |
| `webCitationData` | `IWebCitationApiResponse` | — | Web citation API response (screenshot metadata, URLs, optional message) |
| `webCitationStatus` | `"pending"` \| `"success"` \| `"error"` | inferred | Lifecycle status from parent API call. Inferred from `webCitationData` when omitted |
| `showWebCitation` | `boolean` | web for `GPT_WEB` (uncontrolled) | Active view when `citationType` is `GPT_WEB`. Ignored for `GPT` / `WEB` |
| `onGenerateWebCitation` | `() => void` | — | Called when the user clicks **View Web Citation** and no cached screenshot exists. Parent owns fetch lifecycle (when to call, deduplication, reset) |
| `onToggleCitationView` | `() => void` | — | Called when user toggles between GPT and web views |
| `showExpandImageButton` | `boolean` | `true` | Show/hide full-screen expand on screenshot |
| `showGptMaximizeButton` | `boolean` | `true` | Show/hide GPT header maximize icon (`gptCitation.disableMaximize: true` when `false`) |
| `iconsConfig` | `IGptWebCitationImageIconsConfig` | — | `MaximizeIcon` and `ExternalLinkIcon` overrides for web view |
| `topic` | `string` | auto | Override topic label in web header |
| `sourceLabel` | `string` | auto | Override header source label in web view |
| `relevanceScore` | `number` | auto | Override relevance/decision strength badge (%) |
| `learnedFrom` | `string` | auto | Site name in web footer (auto-derived from `citationUrl`) |
| `sourceModel` | `string` | — | **Deprecated.** Use `sourceLabel` instead |
| `isFixedHeight` | `boolean` | `false` | When `true`, GPT and web panels share the same fixed height/width; screenshot uses `object-fit: contain` |
| `styles` | `IGptWebCitationStyleOverrides` | — | Style overrides for GPT and web citation views (see Usage 5) |

When `isFixedHeight` is `true`, both views use the same panel height (`520px` by default, or `gptCitation.bodyHeight` + toggle footer). Pair with `gptCitation.bodyHeight` to customize the content area (e.g. `"384px"`).

#### `webCitationStatus` inference

When `webCitationStatus` is omitted, the component derives it in this order:

| Priority | Condition | Status |
| --- | --- | --- |
| 1 | Valid screenshot URL in `webCitationData` (`signed_url` or `gs_uri`) | `"success"` (always — image wins over explicit status) |
| 2 | Explicit `webCitationStatus` prop | uses prop value |
| 3 | `webCitationData` present but no image URL | `"error"` |
| 4 | No `webCitationData` | `"pending"` |

Pass `webCitationStatus="pending"` explicitly while your fetch is in flight (before the image URL is available).

### `IGptCitationConfig` (gptCitation prop)

| Field | Type | Description |
|-------|------|-------------|
| `item` | `INonReasoningSource` | GPT reasoning data (`dataSource`, `confidence_score`, highlights, etc.) |
| `headerTitle` | `string` | Panel header title |
| `index` | `number` | Citation index |
| `iconsConfig` | `object` | Icon components (`ChevronDownIcon`, `ChevronUpIcon`, `MaximizeIcon`, `CloseIcon`) |
| `DocumentTitle` | `string` | Source document label shown in the GPT footer (right side). Hidden when `citationType` is `GPT_WEB` or `WEB` |
| `previewCallback` | `() => void` | Called when the source link is clicked |
| `bodyHeight` | `string` | Optional fixed GPT content body height (pair with `styles.webCitation.content`) |
| `disableMaximize` | `boolean` | Disable GPT header fullscreen maximize button (or use `showGptMaximizeButton={false}`) |

### `IGptWebCitationImageIconsConfig` (iconsConfig prop)

| Field | Type | Fallback |
|-------|------|----------|
| `MaximizeIcon` | `ElementType` | `gptCitation.iconsConfig.MaximizeIcon`, then `Maximize2` |
| `ExternalLinkIcon` | `ElementType` | `ExternalLink` |

### Style override types (`styles` prop)

Nested under `styles.webCitation`:

| Type | Keys | Purpose |
| --- | --- | --- |
| `IGptWebCitationVisitLinkStyles` | `row`, `hint`, `link` | Visit link row shared by image footer and skeletons |
| `IGptWebCitationImageStyles` | `wrapper`, `center`, `viewport`, `scrollContainer`, `image`, `expandButton`, `visitLink`, `fullScreen` | Screenshot view + inline loading skeleton while image decodes |
| `IGptWebCitationSkeletonStyles` | `container`, `frame`, `shimmer`, `pending.*`, `error.*`, `visitLink` | Pending/error skeleton UI |
| `IGptWebCitationFullScreenStyles` | `overlay`, `content`, `closeButton`, `imageWrapper`, `image` | Full-screen screenshot modal |

`webCitation.visitLink` merges with scoped `image.visitLink` or `skeleton.visitLink` overrides (scoped wins on conflict).

### `IWebCitationApiResponse` (webCitationData prop)

| Field | Type | Description |
|-------|------|-------------|
| `citationId` | `string` | Unique citation identifier |
| `content` | `string` | HTML/markdown explanation (used for topic/score extraction) |
| `citationType` | `string` | Citation type (e.g. `"web"`) |
| `citationUrl` | `string` | Original source URL (screenshot footer **Visit Link**) |
| `highlightedUrl` | `string` | Highlighted URL from API (preferred for skeleton **Visit Link**) |
| `message` | `string` | API status or error message |
| `imageMetadata` | `object` | Image snapshot metadata |
| `imageMetadata.signed_url` | `string` | Signed URL for screenshot (preferred) |
| `imageMetadata.gs_uri` | `string` | GCS URI fallback for image |
| `db` | `object` | Database metadata (`citation_id`, `blob_path`) |

### Utility helpers

Exported from `@e-llm-studio/citation`:

| Function | Purpose |
| --- | --- |
| `mapCitationDataToDisplay(data)` | Normalizes API response → display fields (`topic`, `highlightedUrl`, `relevanceScore`, etc.) |
| `getWebCitationImageUrl(data)` | Resolves screenshot URL from `imageMetadata` |
| `resolveSkeletonVisitUrl(highlightedUrl, defaultCitationUrl)` | Visit link for pending/error skeletons |
| `extractTopicFromContent(content)` | First anchor text from content |
| `extractRelevanceScoreFromContent(content)` | Parses decision strength / confidence % |
| `extractLearnedFromUrl(citationUrl)` | Hostname → site name for footer |
| `sanitizeExternalUrl(url)` | Safe http(s) URL for links |

### View Behavior

| State | What renders |
|-------|--------------|
| `CitationType.GPT` | GPT citation only (no toggle) |
| `CitationType.WEB` | Web citation only (no toggle) |
| `CitationType.GPT_WEB`, `showWebCitation={false}` | GPT citation + **View Web Citation** button |
| `CitationType.GPT_WEB`, `showWebCitation={true}`, `webCitationStatus="pending"` | Shimmer skeleton + optional **Visit Link** (`highlightedUrl` → `defaultCitationUrl`) |
| `CitationType.GPT_WEB`, `showWebCitation={true}`, `webCitationStatus="success"` | Screenshot (pending skeleton while image loads) + footer **Visit Link** |
| `CitationType.GPT_WEB`, `showWebCitation={true}`, `webCitationStatus="error"` | Error skeleton ("No preview available") + inline **Visit Link** |
| `isFixedHeight={true}` | GPT and web outer panels share height; screenshot `object-fit: contain`; skeleton fills content area |

#### Error skeleton

The error state shows a fixed title ("No preview available"), a restriction message ("This website restricts external previews"), and an inline **Visit Link** when a source URL is available.

### Local Test Component

A test harness is available at `src/features/GptWebCitation/GptWebCitationTest.tsx`. Run the citation dev server with `GptWebCitationTest` mounted in `src/index.tsx` to preview the component interactively. The harness uses `sampleWebCitationApiResponse` from `WebCitationSampleResponse.ts`, simulates a 2s fetch delay when **View Web Citation** is clicked, and accepts `isFixedHeight`, `webCitationStatus`, `iconsConfig`, and `styles` props for local experimentation.

---

## CodeCitation

### Overview

CodeCitation is a composable React UI component for rendering code citations with interactive features, syntax highlighting, and customizable display modes. It provides developers with a powerful tool for displaying code snippets with syntax highlighting, diagnostics, and theme support.

### Features

- **Inline and popup citation views** - Flexible display modes for different use cases
- **Syntax highlighting** - Support for multiple programming languages
- **Dark/Light mode theme toggling** - Accessibility and user preference support
- **Code highlighting** - Highlight specific lines or variables
- **Displaying diagnostics** - Show errors and warnings with customizable styling
- **Fetching code from backend** - Support for dynamic code retrieval
- **Customizable UI** - Extensive customization through props and inline styles
- **Fullscreen view support** - View code in fullscreen modal
- **Responsive design** - Works well on various screen sizes

### Usage

```tsx
import { CodeCitation } from '@e-llm-studio/citation/CodeCitation'

<CodeCitation
 citationTitle="Example Code"
 filename="example.js"
 filepath="/src/example.js"
 customCode={`function hello() { return "world"; }`}
 inLineCitation={true}
 isDarkModeEnabled={false}
 showThemeToggle={true}
 editorHeight={400}
/>
```

**Advanced Features**:
```tsx
const diagnostics = [
 {
 range: { lineStart: 2, lineEnd: 2, columnStart: 6, columnEnd: 11 },
 severity: 1 
 }
]

const highlightRanges = [
 {
 startIndex: 2,
 endIndex: 5,
 color: 'rgba(255, 255, 0, 0.3)',
 lightModeColor: 'rgba(255, 255, 0, 0.2)'
 }
]

<CodeCitation
 customCode={sampleCode}
 diagnostics={diagnostics}
 diagnosticStylesBySeverity={{
 1: { style: { backgroundColor: 'rgba(255,0,0,0.2)' } }
 }}
 startIndex={2}
 endIndex={5}
 isHighlightingEnabled={true}
/>
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `citationTitle` | `string` | Display name for the citation |
| `filename` | `string` | Filename with extension to identify the language |
| `filepath` | `string` | File path for reference |
| `customCode` | `string` | The code string to display in the editor |
| `inLineCitation` | `boolean` | Set to true for inline display or false for popup modal |
| `isDarkModeEnabled` | `boolean` | Enable dark theme by default |
| `showThemeToggle` | `boolean` | Display theme toggle button |
| `editorHeight` | `number` | Height of the code editor in pixels |
| `editorWidth` | `string \| number` | Width of the code editor |
| `baseUrlForCodeRetrieval` | `string` | Base URL for fetching code from backend |
| `assistantName` | `string` | Name of the assistant for context |
| `organizationName` | `string` | Name of the organization |
| `userId` | `string` | User ID for tracking |
| `taskId` | `string` | Task ID for context |
| `repoUrl` | `string` | Repository URL for reference |
| `showFullscreenIcon` | `boolean` | Display fullscreen toggle button |
| `showFileSummaryIButton` | `boolean` | Display file summary info button |
| `isHighlightingEnabled` | `boolean` | Enable code highlighting |

---

## CitationsViewer

### Overview

The Citation Viewer is a rich, interactive React component designed to display AI-generated audio citations. It features a synchronized audio waveform player, a transcript view that highlights active segments, and a summary of key takeaways. This component is ideal for displaying RAG (Retrieval-Augmented Generation) results where the source material is audio or video, allowing users to listen to the specific segment referenced by the AI.

### Features

- **Interactive Waveform** - Visualizes audio using `wavesurfer.js` with playback controls
- **Smart Highlighting** - Automatically highlights the specific time range referenced in the citation on the waveform
- **Synchronized Transcript** - Displays chat history and highlights the active message segment
- **Key Takeaways** - Renders extracted insights with bold text formatting and keyword tags
- **GCS Integration** - Built-in hook to resolve Google Cloud Storage (`gs://`) URLs to signed URLs via a backend endpoint
- **Themable** - Fully customizable colors and typography via a theme config object

### Usage

```tsx
import CitationsViewer from '@e-llm-studio/citation/CitationsViewer'

<CitationsViewer
 artifact={{
 baseUrl: "https://api.example.com",
 artifactTitle: "Quarterly Earnings Call",
 fileUrl: "gs://bucket/audio.mp3",
 chatHistory: [
 {
 role: "Speaker 1",
 message: "Revenue increased by 20%",
 timestamp: "10:30",
 timestamp_start: 120.5,
 timestamp_end: 125.0
 }
 ],
 keyTakeaways: [
 {
 takeawayId: "1",
 name: "Revenue Growth",
 content: "**20% year-over-year growth**",
 keywords: ["Revenue", "Growth"]
 }
 ]
 }}
 onCloseHandler={() => console.log('Closed')}
/>
```

### Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `artifact` | `ArtifactData` | ✅ | The main data object containing audio, transcript, and metadata |
| `onCloseHandler` | `() => void` | ❌ | Callback function triggered when the close (X) button is clicked |
| `theme` | `ThemeConfig` | ❌ | Object to override default colors and fonts |
| `iconsConfig` | `IconsConfig` | ❌ | Object to inject custom React icons (Play, Pause, Close) |

---


## PdfEditorCitation

### Overview

PdfEditorCitation is a core component for the Advanced Document Management and Citation System. It provides a user-friendly interface for viewing, editing, and citing PDF documents directly within the application. It combines interactive PDF viewing capabilities with a collapsible UI pattern, allowing users to manage document space efficiently while maintaining full access to PDF editing and annotation features.

### Features

- **Collapsible PDF viewer functionality** - Users can expand and collapse the PDF editor section
- **Interactive PDF editing capabilities** - Full support for PDF editing, annotations, and collaborative features
- **Sentence highlighting support** - Ability to highlight specific sentences within PDF documents
- **Customizable UI through CSS classes** - Flexible styling options for seamless integration

### Usage

```tsx
import { PdfEditorCitation } from '@e-llm-studio/citation/PdfEditorCitation'

<PdfEditorCitation
 citationTitleElement={<div>Research Paper.pdf</div>}
 pdfUrl="https://example.com/document.pdf"
 pdfEditorBackendBaseUrl="https://pdf-backend.example.com"
 sentenceHighlightDetails={{
 pdfPageNumber: 5,
 sentenceToHighlight: "key finding in the research"
 }}
 currentUserId="user-123"
/>
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `citationTitleElement` | `ReactElement` | A React element to display as the clickable title |
| `pdfUrl` | `string` | The URL of the PDF file to be displayed and edited |
| `pdfEditorBackendBaseUrl` | `string` | The base URL of the PDF editor backend service |
| `citationRootClassName` | `string` | Optional CSS class name for the root container |
| `citationBodyClassName` | `string` | Optional CSS class name for the body section |
| `citationBodyWhenCollapsedClassName` | `string` | Optional CSS class name for collapsed state |
| `citationTitleClassName` | `string` | Optional CSS class name for the title section |
| `rlefEventServiceBaseUrl` | `string` | Optional base URL for the RLEF event service |
| `currentUserId` | `string` | Optional user ID of the current user |
| `sentenceHighlightDetails` | `object` | Optional sentence highlighting configuration |

---


## RequirementAICitation

### Overview

RequirementAICitation is a comprehensive React module for displaying AI-generated insights and rich media evidence. It serves two primary purposes: displaying an AI Reasoning Card with expandable sections for logic, gaps, and confidence scores with embedded citations, and providing standalone media citations for Files, Images, and Web Links.

### Features

- **AI Reasoning Card** - Complex, expandable card displaying AI logic, gaps, and confidence scores with embedded, clickable citations
- **Standalone Media Citations** - Individual, stylized citation pills for Files, Images, and Web Links
- **Multiple Citation Types** - Support for file citations (PDFs), image citations, and web citations
- **Relevance Scoring** - Display AI relevance scores for all citation types
- **Rich Media Preview** - Integrated viewers for PDFs, images, and web content
- **Customizable Styling** - Deep CSS injection for all components

### Usage 1: AI Reasoning Card (Composite Component)
Use this when you want to display AI analysis with embedded, clickable citations that open in a preview panel.

```tsx
import { AiReasoningCitation } from '@e-llm-studio/citation/AiReasoningCitation'

<AiReasoningCitation
  title="AI Analysis"
  aiReasoningAccordionProps={{
    icons: {
      chevronUp: <i className="pi pi-angle-up" />,
      chevronDown: <i className="pi pi-angle-down" />
    }
  }}
  aiReason={{
    id: "1",
    relevance_score: 95,
    reason: ["The <a href='document_citation$1'>ADK.pdf</a> mentions the Agent Card..."],
    gap: ["Registry mechanism is undefined"]
  }}
  citationList={{
    file_citations: [{
      citation_number: "1",
      customMetadata: {
        type: "book_citation_pdf",
        file_name: "ADK.pdf",
        highlighted_pdf_signed_url: "https://storage.googleapis.com/..."
      }
    }],
    image_citations: [],
    web_citations: []
  }}
  
  projectDetails={null}
/>
```

**How Citations Work in AI Reasoning Card:**
- Text contains links like `<a href='document_citation$1'>` or `<a href='image_citation$2'>`
- Clicking a link opens the corresponding citation in a preview panel
- Citation data is looked up from `citationList` using the citation number

---

### Usage 2: Standalone Image Citation

Use this component independently to display an image with relevance scoring.

```tsx
import { ImageCitationContent } from '@e-llm-studio/citation/ImageCitationContent'

<ImageCitationContent
  citationTitle="Visual Reference"
  relevanceScore={95}
  signedUrl="https://images.pexels.com/photo.jpeg"
  
  // Optional: For closeable preview
  closeCitationConfig={{
    CloseIcon: () => <span>✕</span>,
    handleCloseCitationPreview: () => console.log('Closed')
  }}
  
  // Optional: Custom styling
  styles={{
    container: { border: '1px solid #ccc' },
    image: { maxHeight: '500px' },
    aiConfidenceDisplayPill: {
      container: { border: "2px solid blue" }
    }
  }}
/>
```

**With CitationRenderer (Expandable Pill):**
```tsx
import { CitationRenderer } from '@e-llm-studio/citation/CitationRenderer'
import { ImageCitationContent } from '@e-llm-studio/citation/ImageCitationContent'

<CitationRenderer
  inLineCitation={true}
  citationTitle="Screenshot Reference"
  citationComponent={
    <ImageCitationContent
      relevanceScore={95}
      signedUrl="https://images.pexels.com/photo.jpeg"
    />
  }
  chevronDownComponent={<span>▼</span>}
  chevronUpComponent={<span>▲</span>}
/>
```

---

### Usage 3: Standalone File/PDF Citation

Use this component independently to display PDF documents with relevance scoring.

```tsx
import { FileCitationContent } from '@e-llm-studio/citation/FileCitationContent'

<FileCitationContent
  title="Technical Specification.pdf"
  relevanceScore={88}
  signedUrl="https://example.com/sample.pdf"
  
  // Optional: For closeable preview
  closeCitationConfig={{
    CloseIcon: () => <span>✕</span>,
    handleCloseCitationPreview: () => console.log('Closed')
  }}
/>
```

**With CitationRenderer (Expandable Pill):**
```tsx
import { CitationRenderer } from '@e-llm-studio/citation/CitationRenderer'
import { FileCitationContent } from '@e-llm-studio/citation/FileCitationContent'

<CitationRenderer
  inLineCitation={true}
  citationTitle="Technical Spec.pdf"
  citationComponent={
    <FileCitationContent
      title="Spec.pdf"
      relevanceScore={88}
      signedUrl="https://example.com/sample.pdf"
      styles={{ pdfWrapper: { height: "750px" } }}
    />
  }
  chevronDownComponent={<span>▼</span>}
  chevronUpComponent={<span>▲</span>}
/>
```

---

### Usage 4: Standalone Web Citation

Use this component independently to display web content with screenshot preview.

```tsx
import { WebCitationWithImageContent } from '@e-llm-studio/citation/WebCitationWithImageContent'

<WebCitationWithImageContent
  label="Pexels - Free Stock Photos"
  url="https://www.pexels.com/photo/..."
  relevanceScore={92}
  signedUrl="https://images.pexels.com/screenshot.jpeg"
  
  PreviewDialogCloseIcon={() => <span>✕</span>}
  visitIcon={() => <span>→</span>}

  closeCitationConfig={{
    CloseIcon: () => <span>✕</span>,
    handleCloseCitationPreview: () => console.log('Closed')
  }}
/>
```

**With CitationRenderer (Expandable Pill):**
```tsx
import { CitationRenderer } from '@e-llm-studio/citation/CitationRenderer'
import { WebCitationWithImageContent } from '@e-llm-studio/citation/WebCitationWithImageContent'

<CitationRenderer
  inLineCitation={true}
  citationTitle="Pexels Source"
  citationComponent={
    <WebCitationWithImageContent
      label="Pexels Source"
      url="https://www.pexels.com/..."
      relevanceScore={92}
      signedUrl="https://images.pexels.com/screenshot.jpeg"
      PreviewDialogCloseIcon={() => <span>✕</span>}
      visitIcon={() => <span>→</span>}
    />
  }
  chevronDownComponent={<span>▼</span>}
  chevronUpComponent={<span>▲</span>}
/>
```

---

### Usage 5: Standalone Markdown With Image Citation

Use this component when the image should be rendered as part of the markdown content itself rather than as a separate prop-driven media block.

```tsx
import { MarkdownWithImageCitation } from '@e-llm-studio/citation/MarkdownWithImageCitation'

const markdownContent = `
## Product Collaboration Workspace

<img src="https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=1200&q=80" alt="Team collaboration workspace" />

This visual captures a clean product collaboration workspace prepared for planning, note-taking, and design review.

### Key observations

- The laptop acts as the primary working surface for product or engineering review
- The surrounding setup reinforces a structured, research-oriented workflow
- The image is rendered inline as part of the markdown citation
`;

<MarkdownWithImageCitation
  citationTitle="Inline Markdown Image Reference"
  timestamp="Apr 03, 2026 - 11:15 AM"
  relevanceScore={98}
  markdownContent={markdownContent}
  closeCitationConfig={{
    CloseIcon: () => <span>✕</span>,
    handleCloseCitationPreview: () => console.log('Closed'),
  }}
/>
```

**With CitationRenderer (Expandable Pill):**

```tsx
import { CitationRenderer } from '@e-llm-studio/citation/CitationRenderer'
import { MarkdownWithImageCitation } from '@e-llm-studio/citation/MarkdownWithImageCitation'

<CitationRenderer
  inLineCitation={true}
  citationTitle="Markdown Image Reference"
  citationComponent={
    <MarkdownWithImageCitation
      citationTitle="Workspace Note"
      markdownContent={markdownContent}
      relevanceScore={98}
    />
  }
  chevronDownComponent={<span>▼</span>}
  chevronUpComponent={<span>▲</span>}
/>
```

---

### Component Props Reference

#### AiReasoningCitation Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `title` | `string` | ❌ | Title on the main pill | 
| `citationIcon` | `ReactNode` | ❌ | Icon on the main Pill | 
| `aiReason` | `TAIReasoning` | ✅ | Contains `id`, `reason`, `gap`, `relevance_score` |
| `citationList` | `Citations` | ✅ | Lookup object for all referenced files/images/web |
| `aiReasoningAccordionProps` | `Object` | ✅ | Must contain `icons: { chevronUp, chevronDown }` |
| `projectDetails` | `Array` | ❌ | Context for specific app-mod logic |
| `cachingConfig` | `Object` | ❌ | For using `gsUtilPath` instead of `signedUrl` |
| `iconConfig` | `Object` | ❌ | Custom icons: `citationIcon`, `reasoningIcon`, `gapIcon` |
| `titleConfig` | `Object` | ❌ | Custom titles for sections |
| `styles` | `Object` | ❌ | Deep style overrides |

#### ImageCitationContent Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `signedUrl` | `string` | ✅ | Direct URL to the image |
| `gsUtilPath` | `string` | ✅ | GCS Path (requires `cachingConfig`) |
| `citationTitle` | `string` | ❌ | Title shown in header (default: "Visual Reference") |
| `relevanceScore` | `number` | ❌ | Score to display (0-100) |
| `closeCitationConfig` | `Object` | ❌ | `{ CloseIcon, handleCloseCitationPreview }` |
| `cachingConfig` | `Object` | ❌ | For GCS URL resolution |
| `styles` | `Object` | ❌ | Deep style overrides |

*Either `signedUrl` or `gsUtilPath` must be provided

#### FileCitationContent Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `title` | `string` | ✅ | Title shown in the viewer header |
| `signedUrl` | `string` | ✅ | Direct URL to the PDF |
| `gsUtilPath` | `string` | ✅ | GCS Path (requires `cachingConfig`) |
| `relevanceScore` | `number` | ❌ | Score to display (0-100) |
| `closeCitationConfig` | `Object` | ❌ | `{ CloseIcon, handleCloseCitationPreview }` |
| `cachingConfig` | `Object` | ❌ | For GCS URL resolution |
| `styles` | `Object` | ❌ | Deep style overrides including `pdfWrapper` height |

*Either `signedUrl` or `gsUtilPath` must be provided

#### WebCitationWithImageContent Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `url` | `string` | ✅ | The actual link to visit |
| `label` | `string` | ✅ | Text for the link anchor |
| `signedUrl` | `string` | ✅ | URL for the screenshot image |
| `gsUtilPath` | `string` | ✅ | GCS Path (requires `cachingConfig`) |
| `PreviewDialogCloseIcon` | `Component` | ✅ | Icon for fullscreen modal close button |
| `visitIcon` | `Component` | ✅ | Icon for the "Visit Link" button |
| `relevanceScore` | `number` | ❌ | Score to display (0-100) |
| `closeCitationConfig` | `Object` | ❌ | `{ CloseIcon, handleCloseCitationPreview }` |
| `cachingConfig` | `Object` | ❌ | For GCS URL resolution |
| `styles` | `Object` | ❌ | Deep style overrides |

*Either `signedUrl` or `gsUtilPath` must be provided

#### MarkdownWithImageCitation Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `markdownContent` | `string` | ✅ | Markdown/HTML string to render. Inline `<img />` tags are supported. |
| `citationTitle` | `string` | ❌ | Title shown in the header. Defaults to `"Markdown With Image"`. |
| `timestamp` | `string` | ❌ | Optional subtitle shown below the title. |
| `relevanceScore` | `number` | ❌ | Confidence score to display in the header badge (0–100). |
| `closeCitationConfig` | `Object` | ❌ | `{ CloseIcon, handleCloseCitationPreview }` — renders a close button in the header. |
| `styles` | `Object` | ❌ | Deep style overrides for container, header, image wrapper, and markdown regions. |

---

**Required peer dependencies:**
```bash
npm install react-markdown rehype-raw @react-pdf-viewer/core @material-ui/core
```


## VideoCitationContent

### Overview

VideoCitationContent is a React component for rendering video citations with a built-in media player, relevance score display, and optional close button. It supports both direct video URLs and Google Cloud Storage paths (resolved to signed URLs via `cachingConfig`). The player (`react-player`) is loaded dynamically at runtime to avoid bundling it when unused.

### Features

- **Dynamic player loading** — `react-player` is imported at runtime; displays a graceful error if not installed
- **GCS signed URL resolution** — Accepts `gsUtilPath` and resolves it to a playable URL via `cachingConfig`
- **Configurable playback** — Control autoplay, looping, mute, volume, and dimensions via `playerConfig`
- **Relevance score badge** — Displays AI confidence score in the header
- **Optional close button** — Pass `closeCitationConfig` to show a close icon in the header
- **Deep style overrides** — Every visual region is customizable via the `styles` prop

### Usage

```tsx
import { CitationRenderer } from '@e-llm-studio/citation/CitationRenderer'
import VideoCitationContent from '@e-llm-studio/citation/VideoCitationContent'

<CitationRenderer
  inLineCitation={true}
  citationTitle="Video Reference"
  citationComponent={
    <VideoCitationContent
      citationTitle="Demo Video"
      timestamp="March 23, 2026 - 10:45 AM"
      relevanceScore={90}
      videoUrl="https://example.com/sample.mp4"
      playerConfig={{
        controls: true,
        playing: false,
        loop: false,
        muted: false,
        volume: 0.8,
        width: "100%",
        height: "100%",
      }}
      styles={{
        videoWrapper: { minHeight: "400px" },
      }}
    />
  }
  chevronDownComponent={<span>▼</span>}
  chevronUpComponent={<span>▲</span>}
/>
```

**With GCS path (requires `cachingConfig`):**
```tsx
<VideoCitationContent
  citationTitle="Meeting Recording"
  timestamp="March 23, 2026 - 10:45 AM"
  relevanceScore={85}
  gsUtilPath="gs://my-bucket/recordings/meeting.mp4"
  cachingConfig={{
    queryClient,
    useGetSignedUrlQuery,
    useGetSignedUrlMutation,
  }}
  closeCitationConfig={{
    CloseIcon: () => <span>✕</span>,
    handleCloseCitationPreview: () => console.log("Closed"),
  }}
/>
```

> **Note:** `VideoCitationContent` dynamically imports `react-player` at runtime. Ensure it is installed:
> ```bash
> npm install react-player
> ```
> If not installed, the component will display an inline error instead of the player.

### Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `videoUrl` | `string` | ❌ | Direct URL to the video. Takes priority over `gsUtilPath`. |
| `gsUtilPath` | `string` | ❌ | GCS path to the video (requires `cachingConfig` to resolve). |
| `timestamp` | `string` | ❌ | Optional subtitle shown below the title (e.g. a date or time string). |
| `citationTitle` | `string` | ❌ | Title shown in the header. Defaults to `"Video Reference"`. |
| `relevanceScore` | `number` | ❌ | Confidence score to display in the header badge (0–100). |
| `playerConfig` | `Object` | ❌ | Playback overrides — see table below. |
| `closeCitationConfig` | `Object` | ❌ | `{ CloseIcon, handleCloseCitationPreview }` — renders a close button in the header. |
| `cachingConfig` | `Object` | ❌ | `{ queryClient, useGetSignedUrlQuery, useGetSignedUrlMutation }` — required when using `gsUtilPath`. |
| `styles` | `Object` | ❌ | Deep style overrides — see table below. |

*Either `videoUrl` or `gsUtilPath` must be provided.

#### `playerConfig` options

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `controls` | `boolean` | `true` | Show native player controls |
| `playing` | `boolean` | `false` | Autoplay on mount |
| `loop` | `boolean` | `false` | Loop the video |
| `muted` | `boolean` | `false` | Start muted |
| `volume` | `number` | `0.8` | Initial volume (0–1) |
| `width` | `string` | `"100%"` | Player width |
| `height` | `string` | `"100%"` | Player height |

#### `styles` keys

| Key | Description |
|-----|-------------|
| `container` | Outer component wrapper |
| `header` | Header bar (title + right-side actions) |
| `titleGroup` | Wrapper around the title and timestamp |
| `title` | Title text element |
| `timestamp` | Subtitle text shown below the title |
| `headerRight` | Right side of header (score + divider + close) |
| `divider` | Vertical divider between score and close icon |
| `closeIconWrapper` | Clickable wrapper around the close icon |
| `videoWrapper` | Wrapper around the `react-player` instance |
| `loaderContainer` | Centered loader shown while signing URL or loading player |
| `loaderText` | Text below the loader spinner |
| `aiConfidenceDisplayPill.container` | Relevance score badge container |
---
## ScannedDocCitation

### Overview

ScannedDocCitation is a React component for displaying scanned document pages with interactive bounding box highlight overlays. Built for Google Document AI output, it supports multi-page scrolling, highlight navigation via arrows, and a fullscreen view.

### Features

- **Multi-page scrolling** — All pages stacked vertically inside a fixed-height scrollable container
- **Bounding box highlights** — Overlay highlights on document pages using normalized (0–1) coordinates
- **Highlight navigation** — Jump between highlights using ↑↓ arrows, auto-scrolls to active highlight
- **Fullscreen modal** — Expand to a larger view for detailed examination
- **Customizable highlight colors** — Control highlight color, active color, and border color
- **Lazy highlight rendering** — Highlights only appear after the image has fully loaded, preventing bounding boxes from showing on blank pages
- **Pass citationPage** - You can now pass citationPage instead of passing images and highlights as seprate 
- **Control citation label** - You can now use citation lable and control it behaviour by props 

### Usage
```tsx
import ScannedDocCitation from '@e-llm-studio/citation/ScannedDocCitation'

const BACKEND_CITATIONS = [
  {
    customMetaData: {
      citation_number: 1,
      gs_url: "https://storage.googleapis.com/temp_storage_data_ingest/chunk_outputs/123-1121234567512111221102311211201111/_Artifact%20Search%20Response%20format/a0e91e41-255b-404e-a5a3-899f9f760a9a.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=ellm-studio%40proposal-auto-ai-internal.iam.gserviceaccount.com%2F20260311%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20260311T171935Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=1cc5beae8c1a386d182b34044eb1a207d7c11e6477fff242d6d2a1eb23387a85ce3aa763b979feadb41bc176bd8fd4371f813a0446bfb861d1db72a40808fd74bf",
      highlighted_coordinates: [
        { xmin: 0.2855, ymin: 0.5812, xmax: 0.7882, ymax: 0.5915 },
        { xmin: 0.1176, ymin: 0.7006, xmax: 0.8784, ymax: 0.7273 },
      ],
    },
  },
  {
    customMetaData: {
      citation_number: 2,
      gs_url: "https://storage.googleapis.com/temp_storage_data_ingest/chunk_outputs/123-1121234567512111221102311211201111/_Artifact%20Search%20Response%20format/7fef8f3e-25de-4c29-a9be-02dfd9643b0b.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=ellm-studio%40proposal-auto-ai-internal.iam.gserviceaccount.com%2F20260311%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20260311T171935Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=79772ff7ebb758047c11bc276ce5c5a976eec830f96e92e2303da91cee72cdc7e8d22e0d0207b537ab78ba6b7cd7f6bb5808b7bd5fbba61861a5d1478affbb39b4",
      highlighted_coordinates: [
        { xmin: 0.1176, ymin: 0.5885, xmax: 0.7969, ymax: 0.643 },
      ],
    },
  },
  {
    customMetaData: {
      citation_number: 3,
      gs_url: "https://storage.googleapis.com/temp_storage_data_ingest/chunk_outputs/123-1121234567512111221102311211201111/CW%20Buttons%20with%20or%20without%20Cognitive%20Decisioning%20Icons/6f11ae86-53ef-43f0-b21a-4bf52700f68f.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=ellm-studio%40proposal-auto-ai-internal.iam.gserviceaccount.com%2F20260311%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20260311T171935Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=71b4873b97b53c35b529ed4b4ef5c7e6d085c4d4820cd4e7e1ddbabce5cf7975",
      highlighted_coordinates: [
        { xmin: 0.1176, ymin: 0.1624, xmax: 0.8322, ymax: 0.1909 },
        { xmin: 0.1176, ymin: 0.6624, xmax: 0.8329, ymax: 0.6915 },
      ],
    },
  },
]

// Each citation = one page. citation_number is 1-based, pageIndex is 0-based.
const images = BACKEND_CITATIONS.map((c) => c.customMetaData.gs_url)

const highlights = BACKEND_CITATIONS.flatMap((c) =>
  c.customMetaData.highlighted_coordinates.map((coord) => ({
    pageIndex: c.customMetaData.citation_number - 1,
    bboxes: [coord],
  }))
)

<ScannedDocCitation
  images={images}
  highlights={highlights}
  height="700px"
/>
```
### New usage based on pages prop :
```tsx
import ScannedDocCitation from "./features/ScannedDocCitation/ScannedDocCitation";

const BACKEND_CITATIONS = [
  {
    agent_name: "ContextFileAgent",
    title: "ECG_Brainstorming_Integration.pdf",
    url: "https://storage.googleapis.com/...png",
    description: "",
    metadata: {},
    citation_number: 1,
    filter: false,
    artifact_id: "019cfac1-e92e-792b-bdea-960e954d6912",
    customMetaData: {
      citation_number: 1,
      value: [
        {
          gs_url: "https://storage.googleapis.com/...png",
          page_no: 1,
          dimensions: { unit: "pixels", width: 1241, height: 1754 },
          highlighted_coordinates: [
            { xmin: 0.5246, ymin: 0.5547, xmax: 0.6567, ymax: 0.5678 },
          ],
          highlighted_text: [
            {
              text: "stormee x eCG",
              excerpt_from_document: "...",
              page_no: 1,
              reasoning: ["..."],
              gap: ["..."],
              score: 50,
            },
          ],
        },
      ],
    },
  },
];

// Flatten all citation pages
const allPages = BACKEND_CITATIONS.flatMap(
  (c) => c?.customMetaData?.value || []
);

export default function ScannedDocCitationTest() {
  return (
    <div style={{ padding: 16, maxWidth: 720 }}>
      <h3
        style={{
          fontFamily: "Plus Jakarta Sans, sans-serif",
          marginBottom: 12,
        }}
      >
        Scanned Doc Citation Test
      </h3>

      <ScannedDocCitation pages={allPages} />
    </div>
  );
}
```


**With custom highlight colors:**
```tsx
<ScannedDocCitation
  images={imageUrls}
  highlights={highlights}
  highlightColor="rgba(100, 160, 255, 0.3)"
  highlightActiveColor="rgba(100, 160, 255, 0.6)"
  highlightBorderColor="rgba(50, 100, 220, 0.8)"
/>
```

**Single citation at a time:**

If rendering one citation at a time with a single image, always use `pageIndex: 0` regardless of `citation_number`.
```tsx
const images = citation?.customMetaData?.gs_url
  ? [citation.customMetaData.gs_url]
  : [];

const highlights =
  citation?.customMetaData?.highlighted_coordinates?.map((coord) => ({
    pageIndex: 0,  // always 0 since images array has only 1 image
    bboxes: [coord],
  })) ?? [];

return <ScannedDocCitation images={images} highlights={highlights} />;
```

### Props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `pages` | `CitationPage[]` | ✅ | — | Ordered array of `CitationPage` objects containing:<br>• `gs_url`: `string`<br>• `page_no?`: `number`<br>• `highlighted_coordinates?`: `BBox[]`<br>• `dimensions?`: `Dimensions`<br>• `highlighted_text?`: `HighlightedText[]` |
| `images` | `string[]` | ✅ | — | Array of pre-signed GCS image URLs, one per page |
| `highlights` | `PageHighlight[]` | ✅ | — | Array of highlight groups with bounding boxes per page |
| `highlightColor` | `string` | ❌ | `rgba(255, 220, 0, 0.15)` | Background color of inactive highlights |
| `citationLabelColor` | `string` | ❌ | `#FFFF2E` | Background color of the citation label. |
| `subHeadingText` | `string` | ❌ | `""` | Gives you option to add a heading to ScannedDocCitation. |
| `showFullScreenMode` | `boolean` | ❌ | `true` | Gives you option to toggle fullscreen tool in renderNav. |
| `showCitationLabelOnHover` | `boolean` | ❌ | `true` | Show label only on hover (if `false` → always visible). |
| `highlightActiveColor` | `string` | ❌ | `rgba(255, 220, 0, 0.35)` | Background color of the currently active highlight |
| `highlightBorderColor` | `string` | ❌ | `rgba(200, 160, 0, 0.4)` | Border color of the active highlight |
| `height` | `string \| number` | ❌ | `"700px"` | Maximum height of the scrollable container. Shrinks to fit content if content is shorter. |
| `subHeadingTitleInsideModal` | `string` | ❌ | — | Title shown in the fullscreen modal header. Separate from `subHeadingText` which appears above the normal (non-modal) view. |
| `scrollToFirstCitation` | `boolean` | ❌ | `false` | When `true`, automatically scrolls the container to the first citation/bounding box once the page image has loaded. |
| `showPageSeparator` | `boolean` | ❌ | `true` | When `true`, renders a thin horizontal divider line between pages to make page breaks visually distinct. |
| `pageSeparatorColor` | `string` | ❌ | `"#e2e8f0"` | CSS color value for the page separator line. Only used when `showPageSeparator` is `true`. |

### Type Definitions
```typescript
interface BBox {
  xmin: number;  // normalized 0–1 (provided directly by backend)
  ymin: number;
  xmax: number;
  ymax: number;
}

interface PageHighlight {
  pageIndex: number;  // zero-based index matching the images array
  bboxes: BBox[];
}
export interface Dimensions {
  unit: string;
  width: number;
  height: number;
}

export interface HighlightedText {
  text: string;
  excerpt_from_document: string;
  page_no: number;
  reasoning: string[];
  gap: string[];
  score: number;
}

export interface CitationPage {
  gs_url: string;
  page_no?: number;
  highlighted_coordinates?: BBox[];
  dimensions?: Dimensions;
  highlighted_text?: HighlightedText[];
}

interface ScannedDocCitationProps {
  images: string[];
  highlights: PageHighlight[];
  pages?: CitationPage[]; 
  citationLabelColor?: string;
  showCitationLabelOnHover?: boolean;
  highlightColor?: string;
  highlightActiveColor?: string;
  highlightBorderColor?: string;
  height?: string | number;
}
```

> **Note:** Coordinates in `highlighted_coordinates` are already normalized (0–1) by the backend. No pixel conversion needed before passing them to the component.

---

## InstantLearningCitationComponent

### Overview

`InstantLearningCitationComponent` renders markdown content with embedded Instant Learning (IL) citation links. Each citation link is resolved against a provided metadata array and rendered as an expandable inline pill backed by `InstantLearningCitation`. It also supports streaming mode, optional text highlighting, and custom `<details>`/`<summary>` popup patterns.

### Features

- **Inline IL citation pills** — Citation links in markdown are replaced with expandable `CitationRenderer` pills that open a full IL citation card
- **Streaming support** — Shows a slash-loader animation in place of citation pills while the response is still generating
- **Text highlighting** — Highlights a specific phrase in yellow across all rendered text nodes
- **Custom `<details>` rendering** — Handles inline, block, and target `<details>` patterns with animated popup regions

### Usage

```tsx
import InstantLearningCitationComponent from '@e-llm-studio/citation/InstantLearningCitation'

<InstantLearningCitationComponent
  value={MARKDOWN_VALUE}
  citations={CITATIONS_METADATA}
  onCitationToggle={(keys, adId, isOpen) => console.log({ keys, adId, isOpen })}
  isStreaming={false}
/>
```

Citation links in the markdown must follow this format:
```
[LinkText](doc_id=learnings_doc?citationNumber=1&citation_type=IL&citationSource=L1)
```

The `citationNumber` value is matched against `customMetaData.citation_number` in the `citations` array. When `citation_type=IL` and `il_learning` data is present, the link renders as an IL pill; otherwise it falls back to a plain anchor.

**With streaming:**
```tsx
<InstantLearningCitationComponent
  value={streamingMarkdown}
  citations={citations}
  onCitationToggle={handleToggle}
  isStreaming={true}
/>
```

**With text highlighting:**
```tsx
<InstantLearningCitationComponent
  value={markdownContent}
  citations={citations}
  onCitationToggle={handleToggle}
  highlightedText="Testability"
/>
```

### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `string` | ✅ | Markdown content to render, may include IL citation links and `<details>`/`<summary>` tags |
| `citations` | `any[]` | ❌ | Citation metadata array; each item matched by `customMetaData.citation_number`. For IL pills, `citation_type` must be `"IL"` and `il_learning` must be present |
| `onCitationToggle` | `(keys: string[], adId: string, isOpen: boolean) => void` | ✅ | Fired when a citation pill is opened or closed |
| `isStreaming` | `boolean` | ❌ | When `true`, renders an animated slash-loader instead of citation pills (default: `false`) |
| `highlightedText` | `string` | ❌ | Phrase to highlight in yellow across all rendered paragraph, list, and code text |
| `readOnly` | `boolean` | ❌ | Reserved for future editor integration (default: `false`) |
| `height` | `string \| number` | ❌ | Optional container height |

---

# Other Components
## Bookemon

### Overview

Bookemon is a composable, dialog-based React UI component designed for deep book inspection. It features a resizable split-panel layout that allows users to browse detailed metadata while simultaneously viewing and interacting with specific manuscript content. The component is designed to be highly customizable via style injections and handles complex logic for smart text citation, server-side pagination, and focus-mode blurring.

### Features

- **Resizable split-panel layout** - Left panel for metadata, right panel for content preview
- **Deep book inspection** - Browse detailed metadata including overview, elements, copyrights, and awards
- **Smart text citation** - Automatically highlights and focuses on specific text passages
- **Server-side pagination** - Efficiently handles large datasets with pagination support
- **Focus-mode blurring** - Blur non-highlighted text to focus reader attention on relevant content
- **Highly customizable styling** - Inject custom styles for layout containers and citation elements
- **Interactive accordions** - Collapsible sections for book metadata organization


### Usage

```tsx
import Bookemon from '@e-llm-studio/citation/Bookemon'

<Bookemon
 open={isOpen}
 onClose={() => setIsOpen(false)}
 data={bookData}
 getHighlightContent={fetchContent}
 isBlurToggleVisible={true}
/>
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `open` | `boolean` | Controls the visibility of the dialog |
| `onClose` | `() => void` | Callback function triggered when the dialog is closed |
| `data` | `BookemonData` | Object containing book metadata and elements |
| `getHighlightContent` | `(chunkIds: string[]) => Promise<ContentItem[]>` | Async handler to fetch content for highlighting |
| `handleFetchManuscriptElements` | `(params: FetchElementsParams) => Promise<PaginatedResponse>` | Async handler for fetching paginated manuscript elements |
| `isBookemon` | `boolean` | Default: true. Feature flag for Bookemon-specific behavior |
| `isBlurToggleVisible` | `boolean` | Default: false. Shows the blur switch in header |
| `isNonHighlightedBlur` | `boolean` | Default: false. Initial blur state |
| `showComingSoon` | `boolean` | Default: false. Gates the UI with coming soon overlay |
| `customStyle` | `BookemonCustomStyles` | Optional custom styles for layout and citation elements |

---


## DatagestMon

### Overview

DatagestMon is a React component for monitoring and displaying structured data from processing stages (analysis, transform, rag). It provides a comprehensive interface that combines dynamic data visualization with an integrated EPUB viewer. The component uses Material-UI Dialog for display and includes a built-in EPUB reader powered by react-reader.

### Features

- **Multi-stage data display** - Visualize data from analysis, transform, and rag stages
- **Processed and error data** - Display both successful processing results and error information
- **Integrated EPUB viewer** - View associated EPUB content side-by-side with data
- **Dynamic data visualization** - Automatically render various data types
- **Material-UI Dialog** - Professional modal presentation
- **Graceful error handling** - Handle missing or malformed data gracefully

### Usage

```tsx
import DatagestMon from '@e-llm-studio/citation/DatagestMon'

const pipelineData = {
 "analysis": {
 "processed_data": {
 "summary": "Analysis completed",
 "functions": "15 functions extracted"
 },
 "error_data": {
 "rate_limit_exceeded": true
 }
 },
 "transform": {
 "processed_data": {
 "embeddings": 123,
 "transformed_records": 1200
 },
 "error_data": {}
 }
}

<DatagestMon
 open={isOpen}
 onClose={() => setIsOpen(false)}
 data={pipelineData}
 url="https://example.com/document.epub"
/>
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `open` | `boolean` | Controls whether the dialog is open or closed |
| `onClose` | `function` | Callback function triggered when the dialog is closed |
| `data` | `object` | Object containing structured data from processing stages |
| `url` | `string` | Optional URL of the EPUB file to display in the viewer |

---


## DataSelector
 
### Overview

DataSelector is a robust, multi-step wizard designed to handle complex data import workflows. It acts as a central hub where users can select data from various sources—including remote RLEF projects, historical copilot data, saved datasets, or local file uploads—and aggregates them into a unified selection state. It features a built-in state machine for navigation, breadcrumb management, and context-driven state sharing.

### Features

- **Multi-step wizard interface** - Guide users through complex data selection workflows
- **Multiple data sources** - Support for RLEF projects, historical data, saved datasets, and local files
- **Breadcrumb navigation** - Easy navigation through wizard steps
- **Server-side pagination** - Efficiently handle large datasets
- **Search and filtering** - Find data quickly with built-in search
- **State machine navigation** - Robust step management
- **Context-driven state sharing** - Centralized state management via React Context

### Usage

```tsx
import { DataSelectedContextProvider } from '@e-llm-studio/citation/context/DataSelectedContext'
import DataSelector from '@e-llm-studio/citation/DataSelector'

<DataSelectedContextProvider>
 <DataSelector
 pageTitle="Import Dataset"
 selectedRlefResources={resources}
 setSelectedRlefResources={setResources}
 selectedLocalFiles={files}
 setSelectedLocalFiles={setFiles}
 />
</DataSelectedContextProvider>
```

**Wizard Steps**:
1. **Data source selection** - Choose from RLEF, Local, Google Drive, Saved Datasets
2. **Project/task selection** - Select specific projects or tasks
3. **Data collection selection** - Choose from available data collections
4. **Data point selection** - Select specific data points within collections
5. **Final review** - Review and confirm selections


### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `selectedRlefResources` | `Array` | Initial array of selected remote resources |
| `setSelectedRlefResources` | `Function` | State setter for remote resources |
| `selectedLocalFiles` | `Array` | Initial array of selected local files |
| `setSelectedLocalFiles` | `Function` | State setter for local files |
| `pageTitle` | `string` | Customizes the header text |
| `renderDefaultActionsFooter` | `boolean` | Show/hide the default "Next" button |

---

## PaginatedTable

### Overview

PaginatedTable is a high-performance React component designed to display large datasets efficiently. It leverages virtualization (via react-window) to render only the visible rows, ensuring smooth scrolling even with thousands of records. It also supports infinite scrolling, automatically triggering a "load more" callback when the user scrolls near the bottom.

### Features

- **Virtualization** - Efficiently renders massive datasets using windowing
- **Infinite scroll** - Automatically calls onNextPage when scrolling to the bottom
- **Sticky headers** - Headers remain visible while scrolling vertically
- **Horizontal scrolling** - Handles wide tables with a custom scrollbar
- **Loading states** - Displays a skeleton loader row when fetching more data
- **Customizable** - Supports custom dimensions and granular style overrides

### Usage

```tsx
import PaginatedTable from '@e-llm-studio/citation/PaginatedTable'

<PaginatedTable
 headers={["ID", "Name", "Email", "Status"]}
 tableData={users}
 totalFileRecords={10000}
 onNextPage={fetchNextPage}
 loadingMore={isLoading}
 headerRefs={headerRefs}
 columnWidth={200}
 rowHeight={50}
 style={{ height: "600px" }}
/>
```

**Performance Characteristics**:
- Renders only visible rows (windowed rendering)
- Handles thousands of rows efficiently
- Smooth scrolling even with large datasets
- Memory efficient for large data volumes

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `headers` | `string[]` | An array of column header names |
| `tableData` | `Object[]` | Array of data objects where keys match the headers |
| `onNextPage` | `() => void` | Callback triggered when scrolling near the bottom |
| `headerRefs` | `RefObject` | A ref object to store references to header DOM elements |
| `totalFileRecords` | `number` | The total count of records available on the server |
| `loadingMore` | `boolean` | If true, shows a skeleton loader at the bottom |
| `columnWidth` | `number` | Fixed width (in px) for every column |
| `rowHeight` | `number` | Fixed height (in px) for every row |
| `className` | `string` | Custom CSS class for the main container |
| `style` | `CSSProperties` | Inline styles for the main container |
| `styleOverrides` | `Object` | Granular styles for internal elements |

---


## PdfViewer
### Overview 
PdfViewer is a specialized, highly customizable React component designed to render PDF documents with built-in capabilities for text highlighting and highlight navigation. It is built on top of the @react-pdf-viewer library and is optimized for review workflows. It takes a specific list of keywords to highlight and a list of relevant pages, allowing users to "jump" directly between pages that contain relevant information. It supports deep UI overrides via custom classes, styles, and icons to fit seamlessly into any theme.FeaturesText highlighting - Automatically highlight keywords within the documentHighlight navigation - Jump between pages with relevant contentZoom controls - In/out zoom and popover zoom optionsPage navigation - Navigate between highlighted pagesCustom toolbar - Sticky header with navigation controlsDeep UI Customization - Extensive customization through customStyles, customClasses, and customIcons propsResponsive design - Works well on various screen sizesUsageTypeScriptimport PdfViewer from '@e-llm-studio/citation/PdfViewer'

### Usage
```tsx
import PdfViewer from '@e-llm-studio/citation/PdfViewer'
<PdfViewer
 pdfUrl="https://example.com/contract.pdf"
 highlightText={["confidential", "termination", "liability"]}
 highlightPages={[3, 8, 12]}
 jumpToPageValue={3}
 // Optional Customization Hooks
 customStyles={{ 
   pdfIconWrapper: { background: "#ffe4e6", border: "6px solid #fff1f2" },
   pdfName: { color: "#e11d48", fontWeight: "bold" },
 }}
 customClasses={{ 
   actionButton: "p-2 hover:bg-red-100 rounded-lg transition-colors text-red-500", 
 }}
 customIcons={{ 
   pdfIcon: <MyCustomIcon /> 
 }}
/>

### Navigation Behavior
- "Next" button jumps to next page with highlights
- "Previous" button jumps to previous highlighted page
- Direct page navigation based on highlightPages array
- Auto-zoom to actual size on load

### Props
Prop Name	Type	Description
pdfUrl	- string -	The direct URL to the PDF file to be rendered
highlightText - 	string[] -	An array of keywords or phrases to automatically highlight
highlightPages -	number[] -	An object of page numbers (1-based) where highlights appear
jumpToPageValue -	number -	The specific page number to open the document at initially
customStyles -	CustomStylesType -	Optional object to override default inline styles for elements like the viewer wrapper, header, or icons
customClasses -	CustomClassesType -	Optional object to inject custom CSS or Tailwind classes
customIcons - 	CustomIconsType -	Optional object to replace default SVG icons (pdfIcon, fullScreenIcon, downloadIcon, closeIcon)

## ProjectAccordion

### Overview

ProjectAccordion is a React component designed to display project-related information in an accordion format. Further details to be added.

### Features

- Expandable/collapsible accordion design
- Markdown rendering for executive summaries
- Checkbox selection support
- API integration for fetching summaries
- Customizable styling

### Usage

```tsx
import ProjectAccordion from '@e-llm-studio/citation/ProjectAccordion'

<ProjectAccordion
 baseUrl="https://api.example.com"
 taskId="project-123"
 citationTitle="Executive Summary"
 isChecked={selected}
 onCheckChange={(checked) => setSelected(checked)}
 chevronUpComponent={<UpIcon />}
 chevronDownComponent={<DownIcon />}
 styles={{
 pillButton: {
 fontFamily: 'Plus Jakarta Sans, sans-serif',
 border: '0px',
 padding: '8px',
 cursor: 'pointer'
 }
 }}
/>
```

### Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `baseUrl` | string | Yes | API base URL |
| `taskId` | string | Yes | Task/project identifier |
| `citationTitle` | string \| ReactNode | Yes | Accordion header title |
| `isChecked` | boolean | No | Controlled checkbox state |
| `onCheckChange` | function | No | Checkbox change callback |
| `execSummary` | string | No | Pre-fetched summary text |

---


## UploadData

### Overview

UploadData is a feature within the DataSelector component that handles data import from various sources. It provides a comprehensive interface for users to upload data from multiple sources including RLEF projects, Google Drive, local file systems, and saved datasets. The role of its sub-components is to manage the data selection process across different data sources.

### Features

- **Multiple data source support** - Import from RLEF, Google Drive, local files, and saved datasets
- **Unified selection interface** - Aggregate data from various sources
- **File upload handling** - Support for local file uploads
- **Cloud integration** - Google Drive integration for cloud-based data
- **Saved dataset management** - Access and manage previously saved datasets

### Usage

```tsx
import { UploadData } from '@e-llm-studio/citation'
import { DataSelectedProvider } from '@e-llm-studio/citation/context/DataSelectedContext'

<DataSelectedProvider>
 <UploadData />
</DataSelectedProvider>
```

### Upload Sources

- **RLEF Projects**: Data from Research Learning Ecosystem Framework
- **Google Drive**: Cloud-based file storage
- **Local Files**: Direct file upload from device
- **Saved Datasets**: Previously saved data collections


**Integration Example**:
```tsx
import { useSelectDataContext } from '@e-llm-studio/citation/context/DataSelectedContext'

const MyComponent = () => {
 const { selectedRlefResources, saveSelectedDataAsDataSet } = useSelectDataContext()
 
 return (
 <DataSelectedProvider>
 <UploadData />
 <button onClick={() => saveSelectedDataAsDataSet()}>
 Save as Dataset
 </button>
 </DataSelectedProvider>
 )
}
```

---

## ReviewPanel

### Overview

ReviewPanel is a flexible and accessible component for displaying and managing a list of items with review status tracking. It allows users to navigate through items, track completion status, and customize rendering and styling. The component supports both controlled and uncontrolled modes, making it suitable for various use cases from simple item lists to complex review workflows.

### Features

- **Flexible item rendering** - Custom `renderItem` prop for complete control over item appearance
- **Expand/collapse functionality** - Collapsible item list with smooth animations
- **Navigation and status tracking** - Previous/next buttons and visual status indicators
- **Controlled and uncontrolled modes** - Flexible state management options
- **Customizable theming** - Light and dark modes using CSS variables
- **Accessibility support** - Full keyboard navigation and ARIA attributes

### Usage

```tsx
import { ReviewPanel } from '@e-llm-studio/citation/ReviewPanel'

const items = [
  { id: '1', label: 'Item 1' },
  { id: '2', label: 'Item 2' },
  { id: '3', label: 'Item 3' },
];

function App() {
  return (
    <ReviewPanel
      data={items}
      itemConfig={{
        textKey: 'label',
        showStatusIcon: true,
      }}
      theme="dark"
    />
  );
}
```

### Props

| Prop Name | Type | Default | Description |
|-----------|------|---------|-------------|
| `data` | `T[]` | Required | Array of items to display in the review panel |
| `renderItem` | `(params) => ReactNode` | `undefined` | Custom render function for items. If not provided, uses default rendering |
| `itemConfig` | `DefaultItemConfig<T>` | `{}` | Configuration for default item rendering including textKey, showStatusIcon, and showRightBadge |
| `activeIndex` | `number` | `undefined` | Current active item index (controlled mode). When undefined, component manages state internally |
| `onActiveChange` | `(index: number) => void` | `undefined` | Callback fired when active index changes |
| `expanded` | `boolean` | `undefined` | Whether the item list is expanded (controlled mode). When undefined, component manages state internally |
| `onExpandedChange` | `(expanded: boolean) => void` | `undefined` | Callback fired when expanded state changes |
| `headerLeftSlot` | `ReactNode` | `undefined` | Custom content to display on the left side of the header |
| `headerRightSlot` | `(params) => ReactNode` | `undefined` | Custom content to display on the right side of the header |
| `footerSlot` | `ReactNode` | `undefined` | Custom content to display in the footer section |
| `getItemStatus` | `(item: T, index: number) => ReviewStatus` | `undefined` | Function to determine the review status of each item |
| `theme` | `'light' \| 'dark'` | `'dark'` | Color theme for the component |
| `classes` | `ReviewPanelClasses` | `undefined` | Custom CSS class names for component sections |
| `keyExtractor` | `(item: T, index: number) => string` | `(_, i) => i.toString()` | Function to extract unique key for each item |
| `className` | `string` | `undefined` | Custom CSS class for the root container |

---

## TableCitationContent

### Overview

TableCitationContent is a component for rendering tabular data citations with flexible styling and formatting. It automatically discovers columns from data, handles smart formatting for numbers and booleans, and provides built-in support for highlighting specific rows and columns. The component is designed to display structured data in a clean, organized table format with responsive scrolling and sticky headers, making it ideal for presenting data citations, validation results, and metrics in applications.

### Features

- **Automatic column discovery** - Dynamically generates headers from the keys provided in the data rows
- **Smart data formatting** - Automatically formats numbers to fixed decimals and booleans to visual icons (✓/✕)
- **Theming via CSS Variables** - Easily customize appearance using CSS custom properties without modifying source code
- **Highlighting for rows and columns** - Built-in support for highlighting specific rows or columns for emphasis
- **Sticky headers and responsive scrolling** - Keeps table headers visible while scrolling through large datasets with horizontal and vertical scroll support
- **Data validation UI** - Built-in support for highlighting "failed" cells using the `markFailed` property

### Usage

```tsx
import TableCitationContent from '@e-llm-studio/citation/TableCitationContent';

const tableData = [
  { id: 1, name: "Project Alpha", status: true },
  { id: 2, name: "Project Beta", status: false },
];

function App() {
  return (
    <TableCitationContent
      title="Deployment Status"
      timestamp="Feb 04, 2026"
      rows={tableData}
      onClose={() => console.log('Closed')}
    />
  );
}
```

### Props

| Prop Name | Type | Description |
|-----------|------|-------------|
| `rows` | `Record<string, any>[]` | Array of objects representing the table data. Required prop. |
| `title` | `string` | The main title displayed in the header. |
| `timestamp` | `string` | Sub-header text for dates or versions. |
| `highlightColumns` | `string[]` | List of column keys to apply a highlight background. |
| `highlightRowIndex` | `number` | Zero-based index of a specific row to highlight. |
| `onClose` | `() => void` | Callback function triggered when the close button is clicked. |
| `CloseIcon` | `React.ElementType` | Custom React component to use as the close icon. |
| `className` | `string` | Custom CSS class to apply to the root container. |

---

## RuleBookCitationWrapper

A React component used to render Rule Book citation content with highlighted citation phrases.

The component resolves Rule Book citation information either from the provided `data.fileDetails` or from `msg.artifactSearchData.ruleBookData.rulebook_citations`. It then locates the corresponding guideline file, fetches its contents, extracts the Rule Book text, and renders it using `TextualGuideLinesComponent`.


### Usage

```tsx
import RuleBookCitationWrapper from "<library-name>";

<RuleBookCitationWrapper
  data={{
    citationNumber: 1,
  }}
  msg={message}
  guidelines={guidelines}
  getSignedUrl={getSignedUrl}
  getFileContent={getFileContent}
/>
```

---

#### Using Direct File Details

If the citation metadata is already available, it can be passed directly:

```tsx
<RuleBookCitationWrapper
  data={{
    citationNumber: 1,
    fileDetails: {
      file_id: "rulebook-file-id",
      phrase_to_highlight: "Expected Behaviour",
    },
  }}
  guidelines={guidelines}
  getSignedUrl={getSignedUrl}
  getFileContent={getFileContent}
/>
```

In this case, the component skips citation lookup from `msg` and directly loads the corresponding Rule Book file.

### Props

#### `RuleBookCitationWrapperProps`

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `RuleBookCitationData` | `undefined` | Citation metadata. If `fileDetails` is provided, citation lookup is skipped. |
| `msg` | `any` | `undefined` | Message object containing `artifactSearchData.ruleBookData.rulebook_citations`. Used when `fileDetails` is absent. |
| `citationIndex` | `number` | `undefined` | Optional fallback citation index when `data.citationNumber` is unavailable. |
| `guidelines` | `Guidelines` | `[]` | Guideline attachments used to locate the Rule Book file. |
| `additionalClassNames` | `{ container?: string }` | `undefined` | Additional CSS classes applied to the outer container. |
| `getSignedUrl` | `(gcsUrl: string) => Promise<SignedUrlResponse>` | `Required` | Consumer-provided function that returns a signed URL response. |
| `getFileContent` | `(filePath: string) => Promise<string>` | `Required` | Consumer-provided function that returns the JSON file contents. |
| `themeTokens` | `RuleBookCitationThemeTokens` | `undefined` | CSS custom properties used for theming. |
| `classNames` | `RuleBookCitationClassNames` | `undefined` | Custom CSS classes for internal elements. |
| `styles` | `RuleBookCitationStyles` | `undefined` | Inline style overrides for internal elements. |

---

### RuleBookCitationData

| Property | Type | Description |
|----------|------|-------------|
| `citationNumber` | `number` | Citation number (1-based). Internally converted to a zero-based index. |
| `fileDetails.file_id` | `string` | File identifier corresponding to a guideline attachment. |
| `fileDetails.phrase_to_highlight` | `string` | Phrase highlighted inside the Rule Book content. |

---

### Guidelines

The component supports both of the following formats:

```ts
type Guidelines =
  | SourceAttachment[]
  | Record<string, SourceAttachment[]>;
```

---

### SourceAttachment

| Property | Type | Description |
|----------|------|-------------|
| `id` | `string` | Unique identifier matching the citation `file_id`. |
| `gcsUrl` | `string` | GCS path of the Rule Book file. |
| `name` | `string` | File name used to determine the file extension. |
| `is_guideline_file` | `boolean` | Indicates whether the attachment is a guideline file. |

---

### Notes
- `url` is no longer required
- The component no longer makes network calls directly
- Signed URL resolution and file content fetching must be provided through `getSignedUrl` and `getFileContent`
- Theming can also be applied to the nested `TextualGuideLinesComponent` through `themeTokens`, `classNames`, and `styles`

## SplitterCitationsComponent

A responsive, draggable split-pane layout component for React. Renders two panels side-by-side (horizontal) or stacked (vertical) with a draggable divider. Automatically switches to vertical layout when the container is narrower than 500 px. Supports panel collapse/expand and an optional header with a confidence score badge.

### Usage

```tsx
import SplitterCitationsComponent from '@e-llm-studio/citation/SplitterCitations';

<SplitterCitationsComponent
  defaultLeftWidth={50}
  minLeftWidth={200}
  minRightWidth={200}
  height="500px"
  width="900px"
  header={{
    title: "Sources & Guidelines",
    showDocIcon: true,
    confidenceScore: 85,
    confidenceScoreTitle: "AI Relevance",
  }}
  left={<YourLeftComponent />}
  right={<YourRightComponent />}
/>
```

### Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `left` | `React.ReactNode` | — | Content for the left / top panel |
| `right` | `React.ReactNode` | — | Content for the right / bottom panel |
| `defaultLeftWidth` | `number` | `50` | Initial left panel width as a percentage |
| `minLeftWidth` | `number` (px) | `250` | Minimum pixel width of the left panel |
| `minRightWidth` | `number` (px) | `250` | Minimum pixel width of the right panel |
| `height` | `string \| number` | `"400px"` | Height of the component |
| `width` | `string \| number` | `"100%"` | Width of the component |
| `className` | `string` | `""` | Additional CSS class on the root element |
| `header` | `SplitterHeader` | — | Optional header (title, doc icon, confidence score) |
| `onLeftWidthChange` | `(width: number) => void` | — | Callback with left panel pixel width on drag |

**`SplitterHeader` fields:** `title`, `showDocIcon`, `confidenceScore` (0–100), `confidenceScoreTitle`. The badge is green ≥ 80, amber 60–79, red < 60.

---

## CitationOrchestratorComponent

### Overview

`CitationOrchestratorComponent` is the top-level citation dispatcher for the `@e-llm-studio/citation` library. It receives a citation link `href` (with URL search params like `citationNumber` and `citationType`) plus an array of citation data objects, resolves the correct citation by number, and renders the appropriate citation component based on the `citation_type` field — all in a single `<a>`-like element you drop into a markdown renderer.

It handles **seven citation types** out of the box:

| `citation_type` | Renders |
|---|---|
| `scanned_doc_citation` | `ScannedDocCitation` (image pages + highlight boxes) |
| `IL` | `InstantLearningCitationWrapper` (expandable Instant Learning pill) |
| `chat_citation` | `ChatCitationRenderer` (summarized / detailed chat panels + optional rule book) |
| `gpt_citation` | `NonWebReasoningComponent` (GPT / Gemini reasoning card) |
| `web_citation` | `WebCitationWithImageContent` or plain `<a>` |
| `image_citation` | `ImageCitationContent` |
| `document_citation` / `book_citation_doc` / `book_citation_pdf` | `FileCitationContent` |

While streaming, every citation renders a compact spinner via `SlashLoader` instead of its full UI.

### Features

- **Single entry point** — one component dispatches to all citation types; no per-type switch logic needed in the consumer
- **URL-driven resolution** — `citationNumber` and `decisionStrength` are read from `href` query params
- **Streaming-safe** — shows an inline `SlashLoader` spinner while the parent is still generating text
- **Validation with clear errors** — throws descriptive errors for missing required fields; unknown types render nothing and log an error silently
- **Full `ChatCitationConfig` passthrough** — granular control over layout, panels, relevance score, tab defaults, and styles for `chat_citation`
- **Zero opinion on styling** — all visual customization lives in the leaf components or `chatCitationConfig`

### Usage

The component is typically wired into a Markdown renderer as the custom `<a>` component:

```tsx
import CitationOrchestratorComponent from '@e-llm-studio/citation/CitationOrchestratorComponent';

// Inside your markdown renderer config
const renderers = {
  a: ({ href, children }) => (
    <CitationOrchestratorComponent
      href={href}
      citations={citations}
    >
      {children}
    </CitationOrchestratorComponent>
  ),
};
```

The citation link in the markdown source looks like:

```
[L3](doc_id=learnings_doc?citationNumber=1&citation_type=IL&citationSource=L3&decisionStrength=100%)
```

### Props

| Prop | Type | Required | Description |
|---|---|---|---|
| `href` | `string` | Yes | Citation link URL. Must contain `citationNumber` as a query param. `decisionStrength` is also read from here for `IL` citations. |
| `citations` | `CitationItem[]` | Yes | Array of citation objects. Each item must have a `customMetaData` object with at least `citation_type` and `citation_number`. |
| `children` | `React.ReactNode` | No | Link text passed from the markdown renderer. Used as the display label for `IL`, `web_citation`, and `image_citation`. |
| `isStreaming` | `boolean` | No | When `true`, renders an inline spinner instead of the resolved citation. |
| `onCitationToggle` | `(keys: string[], adId: string, isOpen: boolean) => void` | No | Callback forwarded to `InstantLearningCitationWrapper` for toggle state tracking. |
| `chatCitationConfig` | `ChatCitationConfig` | No | Full layout + style configuration for `chat_citation` type. See `ChatCitationConfig` below. |

### `CitationItem` shape

```ts
interface CitationItem {
  customMetaData: {
    citation_type: string;           // dispatcher key
    citation_number?: number | string;

    // scanned_doc_citation
    gs_url?: string;
    highlighted_coordinates?: { xmin: number; ymin: number; xmax: number; ymax: number }[];
    value?: any[];                   // pre-built page array (overrides gs_url path)

    // IL
    il_learning?: any;
    link_text?: string;
    citation_source?: string;
    decision_strength?: string;

    // chat_citation
    chat_data?: ChatCitationDataItem[];
    rule_book_content?: string;
    rule_book_highlights?: string[];
    relevance_score?: number;

    // gpt_citation
    data_sources?: string[];
    training_data_title?: string[];
    paraphrase?: string[];

    // web_citation
    link?: string;
    screenshot_url?: string;

    // image_citation / document citations
    gs_util_path?: string;
    signed_url?: string;

    [key: string]: any;
  };
}
```

### `ChatCitationConfig` prop

Use this to fully control the `chat_citation` rendering without modifying the component:

```ts
interface ChatCitationConfig {
  showRootContainer?: boolean;
  rootContainer?: {
    title?: string;
    relevanceTitle?: string;
    icon?: React.ReactNode;
    slotStyles?: { title?: CSSProperties; relevanceScore?: CSSProperties; container?: CSSProperties };
  };
  chatContainer?: {
    title?: string;
    chatIcon?: React.ReactNode;
    highlightColor?: string;
    summarizedTab?: { chip?: { isActive?: boolean; show?: boolean; styles?: CSSProperties }; view?: { slotStyles?: any } };
    detailedTab?: { chip?: { isActive?: boolean; onClick?: () => void; styles?: CSSProperties }; view?: any };
    slotStyles?: { title?: CSSProperties; chatDataContainer?: CSSProperties; outerContainer?: CSSProperties; container?: CSSProperties };
    additionalSecondaryActions?: React.ReactNode[];
  };
  ruleBookContainer?: {
    title?: string;
    ruleBookIcon?: React.ReactNode;
    slotStyles?: { title?: CSSProperties; dataContainer?: CSSProperties; outerContainer?: CSSProperties };
    additionalSecondaryActions?: React.ReactNode[];
  };
  reversePanels?: boolean;
  isRenderedCustomComponent?: boolean;
  modalContainerStyle?: CSSProperties;
  additionalData?: {
    RuleBookContainerRatio?: number | string;
    RuleBookDetailedViewVerticallyStacked?: boolean;
    RuleBookContainerHeight?: number | string;
  };
  closePreview?: () => void;
  selectedIdFromReason?: string | null;
}
```

### Examples

#### Scanned document with highlight boxes

```tsx
const citations = [{
  customMetaData: {
    citation_type: 'scanned_doc_citation',
    citation_number: 1,
    gs_url: 'https://storage.example.com/doc-page.png',
    highlighted_coordinates: [{ xmin: 100, ymin: 200, xmax: 400, ymax: 250 }],
  }
}];

<CitationOrchestratorComponent href="?citationNumber=1" citations={citations} />
```

#### Chat citation with rule book

```tsx
const citations = [{
  customMetaData: {
    citation_type: 'chat_citation',
    citation_number: 2,
    relevance_score: 87,
    chat_data: [
      { role: 'user', message: 'What is the refund policy?', userName: 'Alice', timeStamp: '2024-01-01T10:00:00Z', highlighted_text: '' },
      { role: 'assistant', message: 'Refunds are processed within 5 business days.', userName: 'Assistant', timeStamp: '2024-01-01T10:00:05Z', highlighted_text: 'Refunds are processed within 5 business days.' },
    ],
    rule_book_content: '**Section 4.2** – Refunds must be requested within 30 days of purchase.',
    rule_book_highlights: ['Refunds must be requested within 30 days'],
  }
}];

<CitationOrchestratorComponent
  href="?citationNumber=2"
  citations={citations}
  chatCitationConfig={{
    showRootContainer: true,
    chatContainer: { summarizedTab: { chip: { isActive: true, show: true } } },
  }}
/>
```

#### Streaming placeholder

```tsx
<CitationOrchestratorComponent
  href="?citationNumber=3&citation_type=IL"
  citations={citations}
  isStreaming={true}
>
  [3]
</CitationOrchestratorComponent>
```

Renders: `[3] ⠋` (spinner) until `isStreaming` becomes `false`.

### Behavior notes

- Returns `null` silently when `citationNumber` is missing from `href` or no matching citation is found in the `citations` array.
- Unknown `citation_type` values also return `null` (with a `console.error`).
- For `web_citation` without a `screenshot_url`, the component falls back to a plain `<a>` tag.
- `chat_citation` defaults: summarized tab active, detailed tab inactive. Override via `chatCitationConfig.chatContainer.summarizedTab` / `detailedTab`.

---

## Common Use Cases

### RAG (Retrieval Augmented Generation) Applications
```tsx
// Display book citations in RAG responses
<BookCitation
 citationTitle="Source: Machine Learning Textbook"
 paragraphs={[relevantParagraph]}
 textToHighlight={[queryKeywords]}
/>

// Show AI reasoning behind answers
<CognitiveDecisioningCard
 score="88"
 reasoning="Based on chapter 3 of the textbook..."
 gap="The textbook doesn't cover recent developments after 2020"
/>
```

### Code Review and Documentation
```tsx
// Display code snippets with diagnostics
<CodeCitation
 filename="utils.js"
 customCode={problematicCode}
 diagnostics={lintErrors}
 isHighlightingEnabled={true}
 startIndex={errorLine - 1}
 endIndex={errorLine + 1}
/>

// Show training data citations for code explanations
<NonWebReasoningComponent
 item={trainingDataCitation}
 index={1}
 headerTitle="Training Data Reference"
/>
```

### Audio/Video Content Analysis
```tsx
// Show audio citations with synchronized transcripts
<CitationsViewer
 artifact={audioAnalysis}
 onCloseHandler={closePlayer}
/>

// Display key takeaways from audio content
<CitationsViewer
 artifact={{
 fileUrl: "gs://bucket/interview.mp3",
 keyTakeaways: [
 {
 takeawayId: "1",
 name: "Key Insight",
 content: "**Important finding** from the interview",
 keywords: ["insight", "finding"]
 }
 ]
 }}
/>
```

### Document Review Workflows
```tsx
// PDF review with highlighting
<PdfViewer
 pdfUrl={contractUrl}
 highlightText={keyClauses}
 highlightPages={relevantPages}
/>

// Collaborative PDF editing
<PdfEditorCitation
 citationTitleElement={<div>Legal Document.pdf</div>}
 pdfUrl={legalDocUrl}
 currentUserId={user.id}
 pdfEditorBackendBaseUrl="https://pdf-backend.example.com"
/>
```

### Data Import and Management
```tsx
// Multi-step data import wizard
<DataSelectedContextProvider>
 <DataSelector
 pageTitle="Import Training Data"
 selectedRlefResources={trainingData}
 setSelectedRlefResources={setTrainingData}
 />
</DataSelectedContextProvider>

// Upload interface wrapper
<DataSelectedProvider>
 <UploadData />
</DataSelectedProvider>
```

### Performance-Optimized Data Display
```tsx
// Virtualized table for large datasets
<PaginatedTable
 headers={columns}
 tableData={largeDataset}
 totalFileRecords={100000}
 onNextPage={loadMoreData}
 loadingMore={loading}
 style={{ height: "500px" }}
/>
```

---


---

## PromptemonBlockViewer

### Overview

A Monaco-based code editor component for viewing and highlighting prompt blocks. Supports XML tag highlighting, variable highlighting, dark/light theme toggling, and a fullscreen dialog with a description panel.

### Features

- **Monaco editor with custom syntax highlighting** — XML tags and `{{variables}}` highlighted with custom token colors
- **XML tag highlighting** — Scrolls to and highlights a specific XML tag block
- **Variable highlighting** — Highlights all occurrences of a `{{variable}}`
- **Dark/light theme toggle** — Switch between themes with a toggle
- **Fullscreen dialog** — Description panel on left, full editor on right

### Usage

```tsx
import PromptemonBlockViewer from '@e-llm-studio/citation/PromptemonBlockViewer'

<PromptemonBlockViewer
  title="role"
  description="This APB establishes the core identity of the AI Assistant."
  content={`<Role>\nYou are a {{ORGANIZATION_NAME}} AI Assistant.\n</Role>`}
  height={300}
  selectedTag="Role"
  highlightVariable="{{ORGANIZATION_NAME}}"
/>
```

### Props

| Prop Name | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `title` | `string` | ✅ | — | Title shown in header and fullscreen dialog |
| `content` | `string` | ✅ | — | Prompt content to display in the editor |
| `description` | `string` | ❌ | — | Description shown in fullscreen left panel |
| `height` | `number` | ❌ | `250` | Height of mini editor in pixels |
| `selectedTag` | `string` | ❌ | — | XML tag name to highlight and scroll to |
| `highlightVariable` | `string` | ❌ | — | Variable string to highlight |

---

## PromptemonViewer

### Overview

A full-featured interface for viewing, editing, and managing Functional Prompt Blocks (FPBs). Combines a detailed left panel showing FPB metadata with a Monaco-based right panel for viewing prompt content and extracted segments. Consumer-controlled — all API calls and state management are handled by the consumer.

### Features

- **Full FPB metadata panel** — Title, description, categories, APBs, applicability, specifications
- **Edit mode** — Inline editing with confirm/cancel flow
- **Segment chips** — Shows extracted `{{variable}}` segments per APB after extraction
- **Monaco editor** — Switches to segmentized content after extraction
- **Extract Segments flow** — Loading overlay while extracting
- **Save FPB** — Enabled after extraction, locks editing after save
- **Category/Sub-category selection** — Consumer provides categories and handles creation

### Usage

```tsx
import PromptemonViewer from '@e-llm-studio/citation/PromptemonViewer'

<PromptemonViewer
  block={myFPBBlock}
  onBlockUpdate={setBlock}
  isExtracting={isExtracting}
  isExtracted={isExtracted}
  onExtractSegments={handleExtractSegments}
  isSaving={isSaving}
  isSaved={isSaved}
  onSave={handleSave}
  onBack={() => navigate(-1)}
  categories={categories}
  subCategories={subCategories}
  selectedCategoryId={selectedCategoryId}
  selectedSubCategoryId={selectedSubCategoryId}
  onCategoryChange={(id) => setSelectedCategoryId(id)}
  onSubCategoryChange={(id) => setSelectedSubCategoryId(id)}
/>
```

### Props

| Prop Name | Type | Required | Description |
|-----------|------|----------|-------------|
| `block` | `any` | ✅ | FPB block object |
| `onBlockUpdate` | `(updatedBlock: any) => void` | ✅ | Called when user confirms edits |
| `isExtracting` | `boolean` | ✅ | Shows loading overlay while true |
| `isExtracted` | `boolean` | ✅ | Shows segment chips and enables Save when true |
| `onExtractSegments` | `() => void` | ✅ | Called when Extract Segments is clicked |
| `isSaving` | `boolean` | ✅ | Shows "Saving..." while true |
| `isSaved` | `boolean` | ✅ | Shows "Saved ✓" and locks editing when true |
| `onSave` | `() => void` | ✅ | Called when Save FPB is clicked |
| `onBack` | `() => void` | ✅ | Called when back/close is clicked |
| `title` | `string` | ❌ | Title shown in top bar (default: "FPB Promptemon") |
| `categories` | `SPBCategory[]` | ✅ | List of categories |
| `subCategories` | `SPBSubCategory[]` | ✅ | List of sub-categories |
| `selectedCategoryId` | `string` | ✅ | Currently selected category ID |
| `selectedSubCategoryId` | `string` | ✅ | Currently selected sub-category ID |
| `onCategoryChange` | `(id: string) => void` | ✅ | Called when category is selected |
| `onSubCategoryChange` | `(id: string) => void` | ✅ | Called when sub-category is selected |
| `onAddCategory` | `(data: { name: string; description: string }) => Promise<void>` | ❌ | Called when new category is created |
| `onAddSubCategory` | `(data: { name: string; description: string; categoryId: string }) => Promise<void>` | ❌ | Called when new sub-category is created |
| `showEditMode` | `boolean` | ❌ | `true` | Show/hide the edit pencil icon and edit mode |
| `showExtractSegments` | `boolean` | ❌ | `true` | Show/hide the Extract Segments button and Show Segments toggle |


## SPBAnalysisPanel

### Overview

A full-featured interface for reviewing the analysis of a System Prompt Block (SPB). Combines a scrollable left panel — Overview, Functionality, Applicability, Specifications, and Dependency Graph — with an optional persistent Monaco-based right panel for viewing the underlying prompt content. Consumer-controlled — all analysis/data fetching is handled by the consumer.

### Features

- **Overview summary** — Collapsible high-level + detailed summary
- **Functionality breakdown** — Nested accordions listing functional areas and their APB references
- **Jump-to-code navigation** — Clicking an APB reference highlights that section in the persistent right-side editor
- **Applicability** — Side-by-side "When to apply" / "When NOT to apply" panels
- **Specifications** — Strict Rules / Input / Output, with automatic `<code>` block extraction in Output
- **Dependency Graph** — Interactive, pannable/zoomable graph of APB relationships
- **Persistent code panel (optional)** — Dark/light toggle and fullscreen expand, togglable via `showCodePanel`
- **Markdown + cognitive decisioning** — Text fields render through a shared markdown renderer supporting citations and expandable "cognitive reasoning" panels

### Usage

```tsx
import SPBAnalysisPanel from '@e-llm-studio/citation/SPBAnalysisPanel'

<SPBAnalysisPanel
  promptContent={mySystemPrompt}
  promptTitle="Persona & Guardrails SPB"
  isLoading={isLoading}
  overviewSummary={overviewSummary}
  functionalityOfSPB={functionalityOfSPB}
  spbAdditionalInfo={spbAdditionalInfo}
  showCodePanel={true}
/>
```

### Props

| Prop Name | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `promptContent` | `string` | ✅ | — | Full system prompt text, rendered in the persistent/fullscreen editor |
| `promptTitle` | `string` | ❌ | `"SPB Analysis"` | Title shown in the header and code panel top bar |
| `isLoading` | `boolean` | ❌ | `false` | Shows skeletons for any section whose data prop is still empty |
| `overviewSummary` | `SPBOverviewSummary \| null` | ❌ | — | Overview section content |
| `functionalityOfSPB` | `SPBFunctionalityItem[]` | ❌ | `[]` | Functional areas and their APB references |
| `spbAdditionalInfo` | `SPBAdditionalInfo \| null` | ❌ | — | Applicability, Specifications, and Dependency Graph content |
| `showCodePanel` | `boolean` | ❌ | `true` | Show/hide the persistent right-side editor panel |

## EmailCitation

A composable React UI component for rendering email-style citations with rich formatting, attachments, and highlight/quote handling. Part of the `@e-llm-studio/citation` package, this component is designed to display email content (subject, sender, recipients, body, attachments, timestamps) in an expandable, accessible, and customizable way.

### Overview

`CitationEmailCard` is a React component that displays email citations with expandable content. It shows core metadata (sender, recipients, subject, date), email body with text highlighting, and attachments. Perfect for surfacing email evidence or correspondence in AI-assisted UIs.

### Features

- **Expandable card view** - Click to toggle between pill button and full email display
- **Text highlighting** - Highlight specific passages based on citations
- **Sender avatar** - Visual indicator with initials
- **Recipient display** - Shows to/cc recipients with tooltip for full list
- **Attachments section** - Expandable list of email attachments
- **Relevance score badge** - Display citation relevance percentage
- **Auto-scroll to highlights** - When expanded, scrolls to first highlighted text
- **Clean email body rendering** - Removes artifacts and formatting noise
- **Customizable icons** - Pass custom icon components to match your design system (no lucide-react dependency required)

### Installation / Import

The component is part of the main citation package:

```bash
npm install @e-llm-studio/citation
```

Import:

```ts
import CitationEmailCard from "@e-llm-studio/citation/EmailCitation";
```

### Basic Usage

The `CitationEmailCard` component exported from `EmailCitation.tsx` expects a small set of props (see Props below). Example usage that matches the component's API:

```tsx
import React from "react";
import CitationEmailCard from "@e-llm-studio/citation/EmailCitation";

const sample = {
    subject: "Update: Project timeline",
    from: "alice@example.com",
    from_name: "Alice Doe",
    from_email: "alice@example.com",
    to: "bob@example.com, carol@example.com",
    cc: null,
    date: "2026-03-10T14:23:00Z",
    body: "Hi team,\nPlease see the updated timeline below...",
};

export default function Example() {
    return (
        <CitationEmailCard
            title="Project Update"
            relevance={87}
            email={sample}
            citations={[{ source_field: "subject", cited_text: "timeline" }]}
            attachments={[{ name: "timeline.pdf", type: "application/pdf" }]}
            toggleLabel="Source Email"
        />
    );
}
```

### Props

This component exposes the following props (mirror of `CitationEmailCardProps` in source):

| Prop | Type | Required | Description |
|---|---:|:---:|---|
| `title` | `string` | No | Optional heading to show instead of the email subject. |
| `relevance` | `number` | Yes | Relevance score shown in the header (percent). |
| `email` | `CitationEmailData` | Yes | Email data object (see type below). |
| `citations` | `CitationItem[]` | No | Array of citation items used to highlight parts of the email. |
| `attachments` | `CitationAttachment[]` | No | Attachments to render in the attachments area. |
| `toggleLabel` | `string` | No | Label for the trigger button (default: `Source Email`). |
| `mailIcon` | `ReactNode` | No | Custom icon for the mail/toggle button (default: lucide Mail icon). |
| `chevronUpIcon` | `ReactNode` | No | Custom icon for expand state (default: lucide ChevronUp icon). |
| `chevronDownIcon` | `ReactNode` | No | Custom icon for collapse state (default: lucide ChevronDown icon). |
| `paperclipIcon` | `ReactNode` | No | Custom icon for attachments button (default: lucide Paperclip icon). |
| `fileTextIcon` | `ReactNode` | No | Custom icon for attachment files (default: lucide FileText icon with color). |
| `downloadIcon` | `ReactNode` | No | Custom icon for download action (default: lucide Download icon). |

### Types (shape)

```ts
// Attachment
type CitationAttachment = { name: string; type?: string };

// Citation item (used to compute highlights)
type CitationItem = { source_field: string; cited_text: string | string[] };

// Email data consumed by the component
type CitationEmailData = {
    subject: string;
    from: string;
    from_name?: string;
    from_email: string;
    to: string; // comma separated list
    cc?: string | null;
    date: string; // ISO timestamp
    body: string; // plain text or HTML
};
```

### Advanced Usage: Custom Icons

If you're not using lucide-react or want to match your design system, pass custom icon components:

```tsx
import React from "react";
import CitationEmailCard from "@e-llm-studio/citation/EmailCitation";
import { FaEnvelope, FaChevronUp, FaChevronDown, FaPaperclip, FaFile, FaDownload } from "react-icons/fa";

export default function CustomIconExample() {
  return (
    <CitationEmailCard
      title="Project Update"
      relevance={87}
      email={sample}
      // Pass your custom icons here
      mailIcon={<FaEnvelope size={14} color="#3B4EE8" />}
      chevronUpIcon={<FaChevronUp size={14} />}
      chevronDownIcon={<FaChevronDown size={14} />}
      paperclipIcon={<FaPaperclip size={14} />}
      fileTextIcon={<FaFile size={16} color="#B42318" />}
      downloadIcon={<FaDownload size={16} />}
    />
  );
}
```

### Notes

- **Highlighting**: Provide `citations` with `source_field` values matching email fields ("subject", "to", "from", "body", "cc") to automatically highlight those passages.
- **Date formatting**: Uses `Intl.DateTimeFormat` with US locale; customize via component modification if needed.
- **Email body cleaning**: The component automatically strips artifacts, page numbers, and excessive whitespace from email bodies.
- **Icon flexibility**: The component comes with lucide-react icons as defaults but is fully customizable. You can pass your own icons (Material-UI, Font Awesome, custom SVGs, etc.) via icon props to seamlessly integrate with your design system.

---



# ManageReminders Component - Complete Usage Guide

## Overview

The `ManageReminders` component provides a flexible, fully customizable reminder and escalation management system. It allows users to configure automatic reminders, escalation rules, and manage assignees with a visual calendar preview.


### Import in Your Component

```typescript
import { ManageReminders } from './components/ManageReminders/ManageReminders';
```

---

## Basic Usage

### Minimal Example

```typescript
import React, { useState } from 'react';
import { ManageReminders } from './components/ManageReminders/ManageReminders';

function MyComponent() {
  const [schedules, setSchedules] = useState([]);
  const [remainderOwners, setRemainderOwners] = useState([
    { id: 1, name: "", email: "", reminder_start_date: "", reminder_frequency: null, days: null, before_or_after: "", escalation_reminder_frequency: null, is_escalation_reminder: false },
    { id: 2, name: "", email: "", reminder_start_date: "", reminder_frequency: null, days: null, before_or_after: "", escalation_reminder_frequency: null, is_escalation_reminder: false },
    { id: 3, name: "", email: "", reminder_start_date: "", reminder_frequency: null, days: null, before_or_after: "", escalation_reminder_frequency: null, is_escalation_reminder: false },
  ]);

  const mockData = {
    due_at: "2026-12-01",
    assignee: {
      1: { name: "John Doe" },
      2: { name: "Jane Smith" },
      3: { name: "Mike Johnson" },
    },
  };

  return (
    <ManageReminders
      data={mockData}
      schedules={schedules}
      setSchedules={setSchedules}
      remainderOwners={remainderOwners}
      setRemainderOwners={setRemainderOwners}
      handelSendNow={() => console.log("Send reminder clicked")}
    />
  );
}
```

---

## Props Reference

### Required Props

| Prop | Type | Description |
|------|------|-------------|
| `data` | `object` | Contains `due_at` (ISO date string) and `assignee` object with user info |
| `schedules` | `any[]` | Array of generated reminder schedules |
| `setSchedules` | `function` | State setter for schedules |
| `remainderOwners` | `remainderOwnerValue[]` | Array of owner configuration objects |
| `setRemainderOwners` | `function` | State setter for remainder owners |
| `handelSendNow` | `function` | Callback triggered when "Send Now" button is clicked |

### Optional Props - Configuration

#### Colors Configuration

```typescript
// Label colors (used for assignee chips)
colors?: ColorConfig[] = [
  { bg: "#FDF2FA", text: "#C11574" },
  { bg: "#EEF4FF", text: "#3538CD" },
  { bg: "#F1F5F9", text: "#344054" },
]

// Statement badge colors
chipColor?: ColorConfig[] = [
  { bg: "#FDF2FA", text: "#C93185" },
  { bg: "#EEF2FF", text: "#6366F1" },
  { bg: "#FFF4E5", text: "#FF6058" },
]

// Recipients avatar colors - USE HEX VALUES, NOT TAILWIND CLASSES
recipientsColor?: ColorConfig[] = [
  { bg: "#DBEAFE", text: "#1E40AF" },  // ✅ Correct: Hex colors
  { bg: "#CCFBF1", text: "#0D9488" },  // ✅ Correct: Hex colors
  { bg: "#DCFCE7", text: "#166534" },  // ✅ Correct: Hex colors
]
```

#### Text Configuration

```typescript
manualReminderTitle?: string = "Send Manual Reminder Now"
manualReminderDescription?: string = "Immediately notify the assignees about this document."
selectRecipientsLabel?: string = "Select recipients:"
previewEmailButtonLabel?: string = "Preview Email"
sendNowButtonLabel?: string = "Send Now"
reminderSuccessTitle?: string = "Reminder sent successfully!"
reminderSuccessDescription?: string = "Email notification sent assignees."

escalationTitle?: string = "Escalation and Auto Reminder Setup"
escalationDescription?: string = "Configure Auto reminder settings for all assignees."

reminderStartDateLabel?: string = "Reminder Start Date"
documentDueDateLabel?: string = "Document Due Date"
reminderFrequencyLabel?: string = "Reminder Frequency"
escalationRemindersLabel?: string = "Escalation Reminders"
escalationConditionText?: string = "If the document is still pending, start escalation reminders"
daysText?: string = "days"
dueDataAndRepeatText?: string = "due date and repeat every"
```

#### Labels and Assignees

```typescript
// Assignee labels (displayed on chips)
labels?: string[] = ["Assignee 1", "Assignee 2", "Assignee 3"]

// Assignee data
assignees?: AssigneeConfig[] = [
  {
    id: "1",
    name: "Assignee 1",
    color: "#C11574",
    bg: "#FDF2F8",
    startDate: new Date("2026-11-09"),
    dueDate: new Date("2026-12-01"),
  },
  // ... more assignees
]

// Fallback recipients when data.assignee is empty
fallbackRecipients?: RecipientConfig[] = [
  {
    initials: "OR",
    name: "Olivia Rhye",
    checked: false,
    bg: "bg-blue-100",
    text: "text-blue-700",
  },
  // ... more recipients
]
```

#### Options

```typescript
reminderFrequencyOptions?: string[] = [
  "12 hours", "24 hours", "48 hours", "72 hours", "Custom"
]

escalationFrequencyOptions?: string[] = [
  "1/2 hour", "1 hour", "4 hours", "6 hours", "12 hours", "Custom"
]

beforeAfterOptions?: string[] = ["After", "Before"]
```

---

## Configuration Examples

### Example 1: Basic Setup with Custom Data

```typescript
const mockData = {
  due_at: "2026-12-15",
  assignee: {
    1: { name: "Alice Johnson" },
    2: { name: "Bob Smith" },
    3: { name: "Carol White" },
  },
};

const customAssignees = [
  { id: "1", name: "Alice Johnson", color: "#C11574", bg: "#FDF2F8", startDate: new Date(), dueDate: new Date("2026-12-15") },
  { id: "2", name: "Bob Smith", color: "#3538CD", bg: "#EEF4FF", startDate: new Date(), dueDate: new Date("2026-12-15") },
  { id: "3", name: "Carol White", color: "#FF6058", bg: "#FFF7ED", startDate: new Date(), dueDate: new Date("2026-12-15") },
];

<ManageReminders
  data={mockData}
  schedules={schedules}
  setSchedules={setSchedules}
  remainderOwners={remainderOwners}
  setRemainderOwners={setRemainderOwners}
  labels={["Alice", "Bob", "Carol"]}
  assignees={customAssignees}
  handelSendNow={() => {
    console.log("Reminders sent!");
    // API call to send reminders
  }}
/>
```

### Example 2: Custom Colors (Correct Way)

```typescript
// ✅ CORRECT: Use hex colors for recipientsColor
const customRecipientsColor = [
  { bg: "#E0E7FF", text: "#3730A3" },    // Indigo
  { bg: "#FDF2F8", text: "#BE185D" },    // Rose
  { bg: "#ECFDF5", text: "#047857" },    // Emerald
];

<ManageReminders
  data={mockData}
  schedules={schedules}
  setSchedules={setSchedules}
  remainderOwners={remainderOwners}
  setRemainderOwners={setRemainderOwners}
  recipientsColor={customRecipientsColor}  // ✅ Pass hex values
  colors={[
    { bg: "#E0E7FF", text: "#3730A3" },
    { bg: "#FDF2F8", text: "#BE185D" },
    { bg: "#ECFDF5", text: "#047857" },
  ]}
  chipColor={[
    { bg: "#E0E7FF", text: "#3730A3" },
    { bg: "#FDF2F8", text: "#BE185D" },
    { bg: "#ECFDF5", text: "#047857" },
  ]}
/>
```

### Example 3: Complete Customization

```typescript
<ManageReminders
  data={mockData}
  schedules={schedules}
  setSchedules={setSchedules}
  remainderOwners={remainderOwners}
  setRemainderOwners={setRemainderOwners}
  
  // Custom labels
  manualReminderTitle="Send Document Notification"
  manualReminderDescription="Notify all recipients about the pending document"
  selectRecipientsLabel="Choose recipients to notify:"
  previewEmailButtonLabel="Preview Message"
  sendNowButtonLabel="Send Notification"
  
  // Custom escalation text
  escalationTitle="Automated Escalation Rules"
  escalationDescription="Set up escalation rules for document tracking"
  
  // Custom field labels
  reminderStartDateLabel="Start Reminding On"
  documentDueDateLabel="Document Deadline"
  reminderFrequencyLabel="Send Reminders Every"
  escalationRemindersLabel="Enable Escalation"
  
  // Custom options
  reminderFrequencyOptions={["6 hours", "12 hours", "24 hours", "Custom"]}
  escalationFrequencyOptions={["1 hour", "2 hours", "4 hours", "Custom"]}
  beforeAfterOptions={["Before deadline", "After deadline"]}
  
  // Callback
  handelSendNow={() => {
    // Send reminders to API
    console.log("Sending reminders...");
  }}
/>
```

---

## Colors and Styling

### ⚠️ IMPORTANT: Color Format Issue & Fix

**The Problem:**
The current code uses Tailwind class names for `recipientsColor`:
```typescript
// ❌ WRONG - These are Tailwind class names
recipientsColor = [
  { bg: "bg-blue-100", text: "text-blue-700" },  // Won't work in inline styles!
]
```


## Development & Contribution

Contributions are welcome! This guide walks you through making changes to the citation library.

### Prerequisites

- **Node.js & npm** installed
- **Git** installed
- Basic familiarity with Git and the command line

### Development Setup

1. **Fork & Clone the Repository**
 ```bash
 git clone https://github.com/<your-username>/citation.git
 cd citation
 ```

2. **Install Dependencies**
 ```bash
 npm install
 ```

3. **Link the Library Locally** (Optional - for testing before publishing)
 ```bash
 git checkout -b my-change-branch
 npm link
 
 # In your test project folder
 npm link @e-llm-studio/citation
 ```

4. **Build the Library**
 ```bash
 npm run build
 ```

5. **Test Locally**
 - Start or build your test project to verify changes work as expected
 - Ensure all existing tests pass

### Making Changes

- Edit source files in the `src/` directory
- Add or update tests as needed
- Follow the existing code style and formatting guidelines
- Ensure your changes are well-documented with comments

### Submitting Changes

1. **Commit Your Changes**
 ```bash
 git add .
 git commit -m "fix: describe your change"
 git push origin my-change-branch
 ```

2. **Submit a Pull Request**
 - Open a pull request on GitHub with a clear description of your changes
 - Reference any related issues
 - Ensure all tests pass before submitting

### Versioning

When publishing updates, follow [Semantic Versioning](https://semver.org/):

```bash
npm version patch # for bug fixes
npm version minor # for new features
npm version major # for breaking changes
```

For more details, refer to the [npm version documentation](https://docs.npmjs.com/cli/v8/commands/npm-version).

### Publishing to npm

> Ensure you have npm account permissions and are on the correct branch.

```bash
npm login
npm publish --access public
```

After publishing, verify the package:

```bash
npm unlink @e-llm-studio/citation
npm install @e-llm-studio/citation@latest
```

### Additional Tips

- Use `npm pack` to generate a `.tgz` and test installation before publishing
- Open a Pull Request when ready for review
- We appreciate your help in improving the citation library through bug fixes, feature enhancements, and documentation improvements

---

## License

This library is released under the MIT License. See the LICENSE file for more details.

The license information is also available in the `citation/package.json` file under the 'license' field.