react-crossword

repository·main·Indexed 42 days ago

https://github.com/jaredreisinger/react-crossword

A flexible, responsive, and easy-to-use crossword component for React applications (v5.2.0). It features high customizability via styled-components, a simplified data format for clues, and support for IPUZ data conversion via the useIpuz hook. The component provides imperative methods for focus, resetting, and validation, as well as callback props to handle player progress events like onCorrect and onCellChange.

Tokens
9.4K
Snippets
28
Records
46
Agent score
52%

What's inside react-crossword

  1. Format crossword data for @jaredreisinger/react-crossword

    main

    The crossword data must be structured as a nested object containing across and down properties. Each property is a map (object) where the keys are the clue numbers (as strings or numbers) and the values are objects defining the clue details.

    Each clue object must include:

    • clue: The text of the clue.
    • answer: The correct answer (typically uppercase).
    • row: The starting row index (0-indexed).
    • col: The starting column index (0-indexed).

    Using a map instead of an array for the clue numbers allows you to control the numbering and labeling of the clues manually.

    {
      across: {
        1: {
          clue: 'one plus one',
          answer: 'TWO',
          row: 0,
          col: 0,
        },
      },
      down: {
        2: {
          clue: 'three minus two',
          answer: 'ONE',
          row: 0,
          col: 2,
        },
      },
    }
  2. Define the Clue/Data format

    main

    The crossword data is structured as a set of nested objects grouped by direction (across and down). Each direction contains a map where keys are the clue numbers (as strings/numbers) and values are objects containing the clue, answer, row, and col.

    {
      across: {
        1: {
          clue: 'one plus one',
          answer: 'TWO',
          row: 0,
          col: 0,
        },
      },
      down: {
        2: {
          clue: 'three minus two',
          answer: 'ONE',
          row: 0,
          col: 2,
        },
      },
    }
  3. Use ThemeProvider for crossword styling

    main

    If you prefer using styled-components' ThemeProvider pattern, the library re-exports ThemeProvider. This allows you to wrap your Crossword component in a provider to inject theme values down the component tree.

    import Crossword, { ThemeProvider } from '@jaredreisinger/react-crossword';
    
    <ThemeProvider
      theme={{
        allowNonSquare: true,
        columnBreakpoint: '9999px',
        gridBackground: '#acf',
        cellBackground: '#ffe',
        cellBorder: '#fca',
        textColor: '#fff',
        numberColor: '#9f9',
        focusBackground: '#f00',
        highlightBackground: '#f99',
      }}
    >
      <Crossword data={data} />
    </ThemeProvider>
  4. Run the react-crossword example app

    main

    To run the local example application provided in this repository, you must first build the core library from the parent directory because the example uses file-relative references for peer dependencies. Follow these steps:

    1. From the parent directory (the crossword library proper), run npm install and then npm build to generate the dist/ files.
    2. Change directory into the example/ folder.
    3. Run npm install within the example/ directory.
    4. Run npm start to launch the demo server.
    5. Visit http://localhost:3000 in your browser.

    Note for real applications: This specific setup is only for the repository's internal example. In a production application, you should install the library normally via npm install @jaredreisinger/react-crossword and manage React and other dependencies through standard package management.

    # From the parent directory
    npm install
    npm build
    
    # Move to the example directory
    cd example
    
    # Install and start
    npm install
    npm start
  5. Configure crossword styling via theme properties

    main

    The Crossword component is highly customizable using a theme object. You can control colors, layout, and responsiveness by providing a theme object. This object can be passed directly to the theme prop on the Crossword component or provided via a ThemeProvider wrapper.

    Available Theme Properties

    PropertyDefaultDescription
    allowNonSquarefalseAllows the crossword to have a different number of rows and columns.
    columnBreakpoint'768px'The browser width at which clues switch from being below the grid to beside the grid.
    gridBackground'rgb(0,0,0)'Background color for the crossword grid. Use 'transparent' to show a page background image.
    cellBackground'rgb(255,255,255)'Background color for an answer cell.
    cellBorder'rgb(0,0,0)'Border color for an answer cell.
    textColor'rgb(0,0,0)'Color for the text entered by the player.
    numberColor'rgba(0,0,0, 0.25)'Color for the across/down numbers in the grid.
    focusBackground'rgb(255,255,0)'Background color for the cell currently being typed into.
    highlightBackground'rgb(255,255,204)'Background color for cells in the current answer and the active clue.
    <Crossword
      data={data}
      theme={{
        gridBackground: '#acf',
        cellBackground: '#ffe',
        cellBorder: '#fca',
        textColor: '#fff',
        numberColor: '#9f9',
        focusBackground: '#f00',
        highlightBackground: '#f99',
      }}
    />
  6. Customize CrosswordGrid appearance via ThemeProvider

    main

    If you are using styled-components, you can provide a theme to all CrosswordGrid components within a tree using ThemeProvider. The CrosswordGrid component merges themes in the following order of precedence (last one wins):

    1. theme prop passed directly to CrosswordGrid (Highest priority)
    2. ThemeContext from styled-components
    3. defaultTheme (Lowest priority)

    Default theme values include:

    • columnBreakpoint: '768px'
    • gridBackground: 'rgb(0,0,0)'
    • cellBackground: 'rgb(255,255,255)'
    • cellBorder: 'rgb(0,0,0)'
    • textColor: 'rgb(0,0,0)'
    • numberColor: 'rgba(0,0,0, 0.25)'
    • focusBackground: 'rgb(255,255,0)'
    • highlightBackground: 'rgb(255,255,204)'
  7. Understand the GridData structure

    main

    The GridData represents the state of the entire crossword grid as a 2D array (CellData[][]). Each element in the array is a CellData object representing a specific GridPosition (row and col).

    CellData can be one of two types:

    1. UsedCellData: A cell that is part of a clue. It includes:

      • used: true
      • answer: The correct single-letter answer for this cell.
      • guess?: The user's current single-letter guess.
      • number?: A display label (e.g., '1').
      • across?: The identifier of the across clue covering this cell.
      • down?: The identifier of the down clue covering this cell.
    2. UnusedCellData: A cell that is not part of any clue. It includes:

      • used: false
      • outOfBounds?: true if the cell is outside the playable area.
    type GridData = CellData[][];
    
    type CellData = UsedCellData | UnusedCellData;
    
    type UsedCellData = {
      row: number;
      col: number;
      used: true;
      answer: string;
      guess?: string;
      number?: string;
      across?: string;
      down?: string;
    };
    
    type UnusedCellData = {
      row: number;
      col: number;
      used: false;
      outOfBounds?: boolean;
    };
  8. Configure Crossword theme properties

    main

    The Crossword component uses styled-components' ThemeProvider. You can pass a theme object directly to the Crossword component or use the re-exported ThemeProvider from the package.

    Available theme properties:

    propertydefaultdescription
    columnBreakpoint'768px'browser-width at which clues move from beneath the grid to beside it
    gridBackground'rgb(0,0,0)'overall background color for the crossword grid
    cellBackground'rgb(255,255,255)'background for an answer cell
    cellBorder'rgb(0,0,0)'border for an answer cell
    textColor'rgb(0,0,0)'color for answer text
    numberColor'rgba(0,0,0, 0.25)'color for the across/down numbers in the grid
    focusBackground'rgb(255,255,0)'background color for the cell with focus
    highlightBackground'rgb(255,255,204)'background color for cells in the current answer/clue
  9. Understand the CluesData format

    main

    While CluesInput is what you provide to start a game, CluesData is the format used to represent the state of the clues during gameplay. It is organized by Direction ('across' or 'down').

    Each clue in the array includes the original input properties plus:

    • number: The display number for the clue.
    • complete?: Whether the answer has been fully entered.
    • correct?: Whether the answer is correct.
    type CluesData = Record<'across' | 'down', (
      ClueTypeOriginal & {
        number: string;
        complete?: boolean;
        correct?: boolean;
      }
    )[]>;