# Component and Hooks

Core React component and hooks for syntax highlighting with flexible render props pattern and fine-grained control over tokenization and styling.

## Capabilities

### Highlight Component

Main React component that provides syntax highlighting through a render props pattern. Handles tokenization, theme application, and provides helper functions for rendering.

```typescript { .api }
/**
 * Main syntax highlighting component using render props pattern
 * @param props - Component props including code, language, theme, and render function
 * @returns JSX element returned by the children render function
 */
interface HighlightProps {
  /** Optional Prism instance (defaults to bundled Prism) */
  prism?: PrismLib;
  /** Optional theme (defaults to vsDark) */
  theme?: PrismTheme;
  /** Programming language for syntax highlighting */
  language: Language;
  /** Code string to highlight */
  code: string;
  /** Render function that receives highlighting data and helper functions */
  children: (props: RenderProps) => JSX.Element;
}

declare const Highlight: React.FC<HighlightProps>;
```

**Usage Examples:**

```typescript
import { Highlight, themes } from "prism-react-renderer";

// Basic usage with custom rendering
<Highlight
  theme={themes.oceanicNext}
  code="const greeting = 'Hello, World!';"
  language="javascript"
>
  {({ className, style, tokens, getLineProps, getTokenProps }) => (
    <pre className={className} style={style}>
      {tokens.map((line, i) => (
        <div key={i} {...getLineProps({ line })}>
          {line.map((token, key) => (
            <span key={key} {...getTokenProps({ token })} />
          ))}
        </div>
      ))}
    </pre>
  )}
</Highlight>

// With line numbers
<Highlight
  theme={themes.vsDark}
  code={multiLineCode}
  language="typescript"
>
  {({ className, style, tokens, getLineProps, getTokenProps }) => (
    <pre className={className} style={style}>
      {tokens.map((line, i) => (
        <div key={i} {...getLineProps({ line, className: "line" })}>
          <span className="line-number">{i + 1}</span>
          {line.map((token, key) => (
            <span key={key} {...getTokenProps({ token })} />
          ))}
        </div>
      ))}
    </pre>
  )}
</Highlight>

// With custom Prism instance
<Highlight
  prism={customPrismInstance}
  theme={themes.github}
  code={code}
  language="python"
>
  {({ tokens, getLineProps, getTokenProps, className, style }) => (
    <pre className={`custom ${className}`} style={style}>
      {/* render implementation */}
    </pre>
  )}
</Highlight>
```

### useTokenize Hook

React hook for tokenizing code using Prism.js. Provides direct access to the tokenization process for custom highlighting implementations.

```typescript { .api }
/**
 * Hook to tokenize code using Prism.js with memoization
 * @param options - Tokenization options including prism instance, code, grammar, and language
 * @returns 2D array of tokens organized by lines
 */
interface TokenizeOptions {
  /** Prism instance to use for tokenization */
  prism: PrismLib;
  /** Code string to tokenize */
  code: string;
  /** Optional grammar for the language (if available) */
  grammar?: PrismGrammar;
  /** Language identifier */
  language: Language;
}

declare function useTokenize(options: TokenizeOptions): Token[][];
```

**Usage Examples:**

```typescript
import { useTokenize, Prism } from "prism-react-renderer";

function CustomHighlighter({ code, language }) {
  const tokens = useTokenize({
    prism: Prism,
    code,
    language,
    grammar: Prism.languages[language]
  });

  return (
    <div className="custom-highlighter">
      {tokens.map((line, lineIndex) => (
        <div key={lineIndex} className="code-line">
          {line.map((token, tokenIndex) => (
            <span 
              key={tokenIndex}
              className={`token ${token.types.join(' ')}`}
              data-empty={token.empty}
            >
              {token.content}
            </span>
          ))}
        </div>
      ))}
    </div>
  );
}

// Using with custom grammar handling
function AdvancedHighlighter({ code, language }) {
  const grammar = Prism.languages[language.toLowerCase()];
  const tokens = useTokenize({
    prism: Prism,
    code,
    language,
    grammar
  });

  if (!grammar) {
    console.warn(`Grammar not found for language: ${language}`);
  }

  // Custom rendering logic
  return <div>{/* render tokens */}</div>;
}
```

### Render Props Helper Functions

The Highlight component provides helper functions through its render props to generate properly styled props for line and token elements. These functions are only available within the children render function of the Highlight component.

**getLineProps Function:**

```typescript { .api }
/**
 * Function to generate props for line elements with proper styling and CSS classes
 * Available in the RenderProps passed to Highlight children function
 */
type GetLineProps = (input: LineInputProps) => LineOutputProps;
```

**getTokenProps Function:**

```typescript { .api }
/**
 * Function to generate props for token elements with proper styling and CSS classes
 * Available in the RenderProps passed to Highlight children function
 */
type GetTokenProps = (input: TokenInputProps) => TokenOutputProps;
```

**Usage Examples:**

```typescript
import { Highlight, themes } from "prism-react-renderer";

// Basic usage of helper functions from render props
function CodeBlock({ code, language }) {
  return (
    <Highlight theme={themes.vsDark} code={code} language={language}>
      {({ className, style, tokens, getLineProps, getTokenProps }) => (
        <pre className={className} style={style}>
          {tokens.map((line, i) => {
            // Use getLineProps to generate proper line attributes
            const lineProps = getLineProps({
              line,
              className: "my-custom-line",
              style: { padding: "0.25rem 0" }
            });
            
            return (
              <div key={i} {...lineProps}>
                {line.map((token, key) => {
                  // Use getTokenProps to generate proper token attributes
                  const tokenProps = getTokenProps({
                    token,
                    className: "my-custom-token"
                  });
                  
                  return <span key={key} {...tokenProps} />;
                })}
              </div>
            );
          })}
        </pre>
      )}
    </Highlight>
  );
}

// Advanced usage with conditional styling
function AdvancedCodeBlock({ code, language, showLineNumbers }) {
  return (
    <Highlight theme={themes.oceanicNext} code={code} language={language}>
      {({ className, style, tokens, getLineProps, getTokenProps }) => (
        <pre className={className} style={style}>
          {tokens.map((line, i) => {
            const lineProps = getLineProps({
              line,
              className: showLineNumbers ? "line-with-number" : "line"
            });
            
            return (
              <div key={i} {...lineProps}>
                {showLineNumbers && (
                  <span className="line-number">{i + 1}</span>
                )}
                {line.map((token, key) => (
                  <span key={key} {...getTokenProps({ token })} />
                ))}
              </div>
            );
          })}
        </pre>
      )}
    </Highlight>
  );
}

## Supporting Types

```typescript { .api }
interface RenderProps {
  /** 2D array of tokens organized by lines */
  tokens: Token[][];
  /** CSS class name for the container */
  className: string;
  /** Inline styles for the container */
  style: CSSProperties;
  /** Function to generate props for line elements */
  getLineProps: (input: LineInputProps) => LineOutputProps;
  /** Function to generate props for token elements */
  getTokenProps: (input: TokenInputProps) => TokenOutputProps;
}

interface TokenizeOptions {
  /** Prism instance to use for tokenization */
  prism: PrismLib;
  /** Code string to tokenize */
  code: string;
  /** Optional grammar for the language (if available) */
  grammar?: PrismGrammar;
  /** Language identifier */
  language: Language;
}
```