# Font and Text Selectors

A collection of toolbar components for font and text formatting including font family selection, font size adjustment, text alignment, and text wrapping options.

## Components Overview

* **FontFamilySelector**: Choose font family (Arial, Times New Roman, etc.)
* **FontSizeSelector**: Select font size in points
* **TextHorizontalAlignSelector**: Horizontal text alignment
* **TextVerticalAlignSelector**: Vertical text alignment
* **TextWrapSelector**: Text wrapping options
* **TextFormatSelector**: Additional text formatting options

## FontFamilySelector

Select the font family for cells.

### Basic Usage

```tsx
import { FontFamilySelector } from "@rowsncolumns/spreadsheet";

<FontFamilySelector
  value={currentCellFormat?.textFormat?.fontFamily}
  onChange={(value) => {
    onChangeFormatting(
      activeSheetId,
      activeCell,
      selections,
      "textFormat",
      { fontFamily: value }
    );
  }}
/>
```

### Complete Example

```tsx
import React, { useState } from "react";
import {
  SpreadsheetProvider,
  CanvasGrid,
  Toolbar,
  FontFamilySelector,
  Sheet,
} from "@rowsncolumns/spreadsheet";
import {
  useSpreadsheetState,
  SheetData,
  CellData,
} from "@rowsncolumns/spreadsheet-state";

function SpreadsheetWithFontSelector() {
  const [sheets, setSheets] = useState<Sheet[]>([
    { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
  ]);
  const [sheetData, setSheetData] = useState<SheetData<CellData>>({});

  const {
    activeCell,
    activeSheetId,
    selections,
    getEffectiveFormat,
    onChangeFormatting,
  } = useSpreadsheetState({
    sheets,
    sheetData,
    onChangeSheets: setSheets,
    onChangeSheetData: setSheetData,
  });

  const currentCellFormat = getEffectiveFormat(
    activeSheetId,
    activeCell.rowIndex,
    activeCell.columnIndex
  );

  return (
    <SpreadsheetProvider>
      <Toolbar>
        <FontFamilySelector
          value={currentCellFormat?.textFormat?.fontFamily}
          onChange={(value) => {
            onChangeFormatting(
              activeSheetId,
              activeCell,
              selections,
              "textFormat",
              { fontFamily: value }
            );
          }}
        />
      </Toolbar>

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

### Props

| Prop        | Type                      | Description                                            |
| ----------- | ------------------------- | ------------------------------------------------------ |
| `value`     | `string`                  | Current font family (e.g., "Arial", "Times New Roman") |
| `onChange`  | `(value: string) => void` | Callback when font family changes                      |
| `className` | `string`                  | Optional CSS class name                                |

### Supported Fonts

Default supported fonts include:

* Arial
* Times New Roman
* Courier New
* Georgia
* Verdana
* Comic Sans MS
* Impact
* Trebuchet MS

## FontSizeSelector

Select font size in points.

### Basic Usage

```tsx
import { FontSizeSelector, DEFAULT_FONT_SIZE_PT } from "@rowsncolumns/spreadsheet";

<FontSizeSelector
  value={currentCellFormat?.textFormat?.fontSize ?? DEFAULT_FONT_SIZE_PT}
  onChange={(value) => {
    onChangeFormatting(
      activeSheetId,
      activeCell,
      selections,
      "textFormat",
      { fontSize: value }
    );
  }}
/>
```

### Props

| Prop        | Type                      | Description                               |
| ----------- | ------------------------- | ----------------------------------------- |
| `value`     | `number`                  | Current font size in points (default: 11) |
| `onChange`  | `(value: number) => void` | Callback when font size changes           |
| `className` | `string`                  | Optional CSS class name                   |

### Common Font Sizes

* 8pt (Very Small)
* 10pt (Small)
* 11pt (Default)
* 12pt (Normal)
* 14pt (Large)
* 18pt (Heading)
* 24pt (Large Heading)
* 36pt (Display)

## TextHorizontalAlignSelector

Horizontal text alignment selector.

### Basic Usage

```tsx
import { TextHorizontalAlignSelector } from "@rowsncolumns/spreadsheet";

<TextHorizontalAlignSelector
  value={currentCellFormat?.horizontalAlignment}
  onChange={(value) => {
    onChangeFormatting(
      activeSheetId,
      activeCell,
      selections,
      "horizontalAlignment",
      value
    );
  }}
/>
```

### Props

| Prop        | Type                            | Description                     |
| ----------- | ------------------------------- | ------------------------------- |
| `value`     | `"left" \| "center" \| "right"` | Current horizontal alignment    |
| `onChange`  | `(value) => void`               | Callback when alignment changes |
| `className` | `string`                        | Optional CSS class name         |

### Alignment Options

* **Left**: Align text to the left (default for text)
* **Center**: Center text horizontally
* **Right**: Align text to the right (default for numbers)

## TextVerticalAlignSelector

Vertical text alignment selector.

### Basic Usage

```tsx
import { TextVerticalAlignSelector } from "@rowsncolumns/spreadsheet";

<TextVerticalAlignSelector
  value={currentCellFormat?.verticalAlignment}
  onChange={(value) => {
    onChangeFormatting(
      activeSheetId,
      activeCell,
      selections,
      "verticalAlignment",
      value
    );
  }}
/>
```

### Props

| Prop        | Type                            | Description                     |
| ----------- | ------------------------------- | ------------------------------- |
| `value`     | `"top" \| "middle" \| "bottom"` | Current vertical alignment      |
| `onChange`  | `(value) => void`               | Callback when alignment changes |
| `className` | `string`                        | Optional CSS class name         |

### Alignment Options

* **Top**: Align text to top of cell
* **Middle**: Center text vertically (default)
* **Bottom**: Align text to bottom of cell

## TextWrapSelector

Text wrapping options.

### Basic Usage

```tsx
import { TextWrapSelector } from "@rowsncolumns/spreadsheet";

<TextWrapSelector
  value={currentCellFormat?.wrapStrategy}
  onChange={(value) => {
    onChangeFormatting(
      activeSheetId,
      activeCell,
      selections,
      "wrapStrategy",
      value
    );
  }}
/>
```

### Props

| Prop        | Type                             | Description                         |
| ----------- | -------------------------------- | ----------------------------------- |
| `value`     | `"overflow" \| "clip" \| "wrap"` | Current wrap strategy               |
| `onChange`  | `(value) => void`                | Callback when wrap strategy changes |
| `className` | `string`                         | Optional CSS class name             |

### Wrap Options

* **Overflow**: Text overflows into adjacent cells (default)
* **Clip**: Text is clipped at cell boundary
* **Wrap**: Text wraps within the cell

## TextFormatSelector

Additional text formatting options.

### Basic Usage

```tsx
import { TextFormatSelector } from "@rowsncolumns/spreadsheet";

<TextFormatSelector
  value={currentCellFormat?.textRotation}
  onChange={(value) => {
    onChangeFormatting(
      activeSheetId,
      activeCell,
      selections,
      "textRotation",
      value
    );
  }}
/>
```

### Props

| Prop        | Type                      | Description                             |
| ----------- | ------------------------- | --------------------------------------- |
| `value`     | `number`                  | Text rotation angle (-90 to 90 degrees) |
| `onChange`  | `(value: number) => void` | Callback when rotation changes          |
| `className` | `string`                  | Optional CSS class name                 |

## Complete Toolbar Example

```tsx
import React, { useState } from "react";
import {
  SpreadsheetProvider,
  CanvasGrid,
  Toolbar,
  ToolbarSeparator,
  FontFamilySelector,
  FontSizeSelector,
  TextHorizontalAlignSelector,
  TextVerticalAlignSelector,
  TextWrapSelector,
  ButtonBold,
  ButtonItalic,
  ButtonUnderline,
  DEFAULT_FONT_SIZE_PT,
  Sheet,
} from "@rowsncolumns/spreadsheet";
import {
  useSpreadsheetState,
  SheetData,
  CellData,
} from "@rowsncolumns/spreadsheet-state";

function SpreadsheetWithTextFormatting() {
  const [sheets, setSheets] = useState<Sheet[]>([
    { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
  ]);
  const [sheetData, setSheetData] = useState<SheetData<CellData>>({});

  const {
    activeCell,
    activeSheetId,
    selections,
    getCellData,
    getEffectiveFormat,
    onChangeActiveCell,
    onChangeSelections,
    onChangeFormatting,
  } = useSpreadsheetState({
    sheets,
    sheetData,
    onChangeSheets: setSheets,
    onChangeSheetData: setSheetData,
  });

  const currentCellFormat = getEffectiveFormat(
    activeSheetId,
    activeCell.rowIndex,
    activeCell.columnIndex
  );

  return (
    <SpreadsheetProvider>
      <div className="flex flex-col h-screen">
        <Toolbar>
          {/* Font Family */}
          <FontFamilySelector
            value={currentCellFormat?.textFormat?.fontFamily}
            onChange={(value) => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "textFormat",
                { fontFamily: value }
              );
            }}
          />

          {/* Font Size */}
          <FontSizeSelector
            value={currentCellFormat?.textFormat?.fontSize ?? DEFAULT_FONT_SIZE_PT}
            onChange={(value) => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "textFormat",
                { fontSize: value }
              );
            }}
          />

          <ToolbarSeparator />

          {/* Bold, Italic, Underline */}
          <ButtonBold
            active={currentCellFormat?.textFormat?.bold}
            onClick={() => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "textFormat",
                { bold: !currentCellFormat?.textFormat?.bold }
              );
            }}
          />

          <ButtonItalic
            active={currentCellFormat?.textFormat?.italic}
            onClick={() => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "textFormat",
                { italic: !currentCellFormat?.textFormat?.italic }
              );
            }}
          />

          <ButtonUnderline
            active={currentCellFormat?.textFormat?.underline}
            onClick={() => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "textFormat",
                { underline: !currentCellFormat?.textFormat?.underline }
              );
            }}
          />

          <ToolbarSeparator />

          {/* Text Alignment */}
          <TextHorizontalAlignSelector
            value={currentCellFormat?.horizontalAlignment}
            onChange={(value) => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "horizontalAlignment",
                value
              );
            }}
          />

          <TextVerticalAlignSelector
            value={currentCellFormat?.verticalAlignment}
            onChange={(value) => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "verticalAlignment",
                value
              );
            }}
          />

          {/* Text Wrapping */}
          <TextWrapSelector
            value={currentCellFormat?.wrapStrategy}
            onChange={(value) => {
              onChangeFormatting(
                activeSheetId,
                activeCell,
                selections,
                "wrapStrategy",
                value
              );
            }}
          />
        </Toolbar>

        <div className="flex-1">
          <CanvasGrid
            sheetId={activeSheetId}
            activeCell={activeCell}
            selections={selections}
            getCellData={getCellData}
            onChangeActiveCell={onChangeActiveCell}
            onChangeSelections={onChangeSelections}
          />
        </div>
      </div>
    </SpreadsheetProvider>
  );
}

export default SpreadsheetWithTextFormatting;
```

## Keyboard Shortcuts

Common keyboard shortcuts for text formatting:

* **Ctrl/Cmd + B**: Toggle bold
* **Ctrl/Cmd + I**: Toggle italic
* **Ctrl/Cmd + U**: Toggle underline
* **Ctrl/Cmd + L**: Align left
* **Ctrl/Cmd + E**: Align center
* **Ctrl/Cmd + R**: Align right

## Styling

Customize selector appearance with CSS:

```tsx
<FontFamilySelector
  className="min-w-32 border rounded"
  value={fontFamily}
  onChange={onChange}
/>

<FontSizeSelector
  className="w-16"
  value={fontSize}
  onChange={onChange}
/>
```

## Best Practices

1. **Show Current Format**: Always display the current cell's formatting state
2. **Multi-Selection Support**: Apply formatting to all selected cells
3. **Use getEffectiveFormat**: Get the computed format including defaults
4. **Provide Visual Feedback**: Highlight active formatting buttons
5. **Group Related Controls**: Use ToolbarSeparator to organize formatting options

## Use Cases

### Custom Font Lists

Provide custom font families:

```tsx
const customFonts = [
  "Roboto",
  "Open Sans",
  "Lato",
  "Montserrat",
  "Raleway",
];

<FontFamilySelector
  fonts={customFonts}
  value={fontFamily}
  onChange={onChange}
/>
```

### Font Size Presets

Common font size presets:

```tsx
const fontSizePresets = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36];

<FontSizeSelector
  presets={fontSizePresets}
  value={fontSize}
  onChange={onChange}
/>
```

### Conditional Formatting

Apply different alignments based on data type:

```tsx
const handleAlignmentChange = (value) => {
  const cellData = getCellData(activeSheetId, activeCell.rowIndex, activeCell.columnIndex);

  // Auto-align numbers to the right
  if (typeof cellData?.effectiveValue?.numberValue === "number") {
    value = "right";
  }

  onChangeFormatting(activeSheetId, activeCell, selections, "horizontalAlignment", value);
};
```

## Troubleshooting

### Selectors Not Showing Current Value

* Ensure getEffectiveFormat returns the correct cell format
* Check that activeCell and selections are properly synced
* Verify formatting data is stored correctly in sheetData

### Font Changes Not Applying

* Confirm onChangeFormatting is called with correct parameters
* Check that the font family name matches exactly
* Ensure the font is loaded (use loadWebFont for custom fonts)

### Performance Issues

* Memoize currentCellFormat calculation
* Debounce onChange handlers for font size input
* Use React.memo for selector components

## See Also

* [Toolbar](https://docs.rowsncolumns.app/configuration/components/toolbar) - Main toolbar component
* [Text Color Selector](https://docs.rowsncolumns.app/configuration/toolbar#textcolorselector) - Text color picker
* [Background Color Selector](https://docs.rowsncolumns.app/configuration/toolbar#backgroundcolorselector) - Background color picker
* [Border Selector](https://docs.rowsncolumns.app/configuration/toolbar#borderselector) - Cell border formatting
