# Structured Cell Renderer

The Structured Cell Renderer allows you to render custom visualizations and content within spreadsheet cells. Instead of displaying plain text, you can render rich content like sparklines, charts, or any custom component.

## Overview

Structured results are special cell values that contain both data and rendering instructions. The spreadsheet automatically detects these structured values and renders them using the `StructuredResultRenderer` component.

## Supported Structured Results

### Sparklines

Sparklines are small inline charts that fit within a cell, perfect for visualizing trends in data.

```typescript
import type { SparkLineResult } from "@rowsncolumns/common-types";

const sparklineValue: SparkLineResult = {
  kind: "sparkline",
  data: [1, 5, 3, 7, 4, 9, 6],
  formattedValue: "Trend", // Fallback text
};
```

The sparkline will automatically render as a mini chart within the cell.

### Custom Structured Results

You can create your own structured result types by extending the `StructuredResult` interface:

```typescript
import type { StructuredResult } from "@rowsncolumns/common-types";

type MyCustomResult = {
  kind: "custom";
  data: any;
  formattedValue: string;
} & StructuredResult;
```

## Using Structured Cells

### 1. Define Your Custom Cell Data Type

```typescript
import type { CellData, StructuredResult } from "@rowsncolumns/spreadsheet";

type MyStructuredResult = {
  kind: "sparkline" | "custom";
  data: any[];
  formattedValue: string;
} & StructuredResult;

type MyCustomCellData = CellData<MyStructuredResult>;
```

### 2. Create Structured Cell Values

```typescript
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state";

const { onChangeBatch } = useSpreadsheetState({
  // ... other props
});

// Add a sparkline to a cell
onChangeBatch(
  sheetId,
  {
    startRowIndex: 1,
    endRowIndex: 1,
    startColumnIndex: 1,
    endColumnIndex: 1,
  },
  [{
    ev: {
      structuredValue: {
        kind: "sparkline",
        data: [1, 5, 3, 7, 4, 9, 6],
        formattedValue: "Trend",
      }
    }
  }]
);
```

### 3. Custom Renderer (Optional)

If you need custom rendering logic beyond sparklines, you can provide your own `StructuredResult` component to `CanvasGrid`:

```typescript
import { Text } from "react-konva";
import type { StructuredResultProps } from "@rowsncolumns/spreadsheet";

const MyStructuredRenderer = (props: StructuredResultProps) => {
  const { structuredValue, ...rest } = props;
  
  if (structuredValue?.kind === "custom") {
    return (
      <Text
        {...rest}
        text={`Custom: ${structuredValue.formattedValue}`}
        fill="blue"
      />
    );
  }
  
  // Fallback to default renderer
  return null;
};

// Use in CanvasGrid
<CanvasGrid
  StructuredResult={MyStructuredRenderer}
  // ... other props
/>
```

## Getting Structured Values

You can access structured cell values through the spreadsheet state:

```typescript
const { getUserEnteredExtendedValue, getEffectiveExtendedValue } = useSpreadsheetState({
  // ... props
});

// Get the user-entered structured value
const userValue = getUserEnteredExtendedValue(sheetId, rowIndex, columnIndex);
console.log(userValue?.structuredValue);

// Get the computed/formatted structured value
const effectiveValue = getEffectiveExtendedValue(sheetId, rowIndex, columnIndex);
console.log(effectiveValue?.structuredValue);
```

## Formulas and Structured Results

You can create formulas that return structured results:

```typescript
import type FormulaParser from "@rowsncolumns/fast-formula-parser";
import type { FunctionArgument } from "@rowsncolumns/calculator";

const SPARKLINE = (parser: FormulaParser, dataRange: FunctionArgument) => {
  // Extract values from the range
  const values = dataRange.value; // Array of cell values
  
  return {
    kind: "sparkline",
    data: values.map(Number),
    formattedValue: `Sparkline(${values.length} points)`,
  };
};

// Register the function
const functions = {
  ...defaultFunctions,
  SPARKLINE,
};

// Use in a cell
// =SPARKLINE(A1:A10)
```

## Complete Example

```typescript
import React, { useState } from "react";
import {
  SpreadsheetProvider,
  CanvasGrid,
  type CellData,
  type StructuredResult,
} from "@rowsncolumns/spreadsheet";
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state";

type MyStructuredResult = {
  kind: "sparkline";
  data: number[];
  formattedValue: string;
} & StructuredResult;

type MyCustomCellData = CellData<MyStructuredResult>;

function SpreadsheetWithStructuredCells() {
  const [sheets, setSheets] = useState([
    { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
  ]);
  const [sheetData, setSheetData] = useState<SheetData<MyCustomCellData>>({
    1: [
      null,
      {
        values: [
          null,
          {
            ev: {
              structuredValue: {
                kind: "sparkline",
                data: [1, 5, 3, 7, 4, 9, 6, 8, 5],
                formattedValue: "Sales Trend",
              },
            },
          },
        ],
      },
    ],
  });

  const {
    activeCell,
    activeSheetId,
    selections,
    getCellData,
    // ... other hook values
  } = useSpreadsheetState({
    sheets,
    sheetData,
    onChangeSheets: setSheets,
    onChangeSheetData: setSheetData,
  });

  return (
    <SpreadsheetProvider>
      <CanvasGrid
        sheetId={activeSheetId}
        activeCell={activeCell}
        selections={selections}
        getCellData={getCellData}
        // ... other props
      />
    </SpreadsheetProvider>
  );
}
```

## Use Cases

### Visualizing Trends

Sparklines are perfect for showing trends in financial data, metrics, or time series:

```typescript
// Sales data with inline trend visualization
const salesData = {
  ev: {
    structuredValue: {
      kind: "sparkline",
      data: monthlySales, // [100, 120, 115, 140, ...]
      formattedValue: "$1,234 total",
    },
  },
};
```

### Custom Indicators

Create custom visual indicators for status, progress, or ratings:

```typescript
type StatusResult = {
  kind: "status";
  status: "good" | "warning" | "error";
  formattedValue: string;
} & StructuredResult;
```

## Performance Considerations

* Structured results are rendered using canvas (react-konva), providing excellent performance even with many cells
* Complex visualizations should be optimized to avoid rendering bottlenecks
* Consider using `formattedValue` as a text fallback for export and copy operations

## Limitations

* Structured results are visual-only and don't affect cell value calculations
* When copying cells with structured results, the `formattedValue` is used as text
* Excel export will show the `formattedValue` as plain text
