# useDocumentSearch

Source: https://sdk.pdf.net/docs/v1/reference/useDocumentSearch



Searches the document text: set a query, step through the matches, and let the SDK highlight them on the pages and scroll to the active one. Re-renders the component as the search progresses.

```ts
const {
  criteria,
  matches,
  activeMatchIndex,
  status,
  setSearchCriteria,
  goToNextMatch,
  goToPreviousMatch,
  goToMatch,
} = useDocumentSearch()
```

Every hook call shares the same search, so a search bar and a results list in different components stay in sync. Each loaded document starts with an empty query and every option off.

## State [#state]

| Field              | Type                     | Meaning                                                                                |
| ------------------ | ------------------------ | -------------------------------------------------------------------------------------- |
| `criteria`         | `SearchCriteria`         | The query and the options, as last set.                                                |
| `matches`          | `readonly SearchMatch[]` | The matches in document order: page by page, and within a page paragraph by paragraph. |
| `activeMatchIndex` | `number`                 | The index of the active match in `matches`, or `-1` when no match is active.           |
| `status`           | `SearchStatus`           | How far the search has gone through the document.                                      |

`SearchCriteria` fields:

| Field             | Type      | Meaning                                                                                                        |
| ----------------- | --------- | -------------------------------------------------------------------------------------------------------------- |
| `query`           | `string`  | The text to find. `''` means no search.                                                                        |
| `isCaseSensitive` | `boolean` | Match the letter case of the query exactly.                                                                    |
| `isWholeWord`     | `boolean` | Skip occurrences that continue a word on either side. Letters, digits, combining marks, and `_` make up words. |

`SearchMatch` fields:

| Field         | Type     | Meaning                                                                                                                      |
| ------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `id`          | `string` | Identifies the match for React keys and `goToMatch` (session-scoped).                                                        |
| `pageId`      | `string` | The page the match is on, as the page hooks such as [useScrollToPage](https://sdk.pdf.net/docs/v1/reference/useScrollToPage) accept it.         |
| `paragraphId` | `string` | The paragraph the match is in, as the block hooks such as [useScrollToBlock](https://sdk.pdf.net/docs/v1/reference/useScrollToBlock) accept it. |
| `text`        | `string` | The matched text as it appears in the document.                                                                              |

`SearchStatus` is one of:

| Status        | Meaning                                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------------------------- |
| `'idle'`      | There is no query.                                                                                                |
| `'searching'` | The criteria changed and the search hasn't gone through the whole document yet. `matches` grows meanwhile.        |
| `'complete'`  | The whole document is searched. The matches keep following the edits. A page whose text fails to load is skipped. |

## Actions [#actions]

* `setSearchCriteria(criteria)` starts a search for new criteria. To change one field, spread `criteria` into the call: `setSearchCriteria({ ...criteria, isWholeWord: true })`.
  * A changed query is searched once typing pauses, so `status` is `'searching'` with no matches for a moment.
  * Changing an option without changing the query searches at once.
  * The first match found becomes active and is scrolled to.
  * A query of `''` drops the matches and every highlight.
  * Criteria equal to the current ones change nothing.
* `goToNextMatch()` and `goToPreviousMatch()` activate the next or previous match and scroll to it, wrapping around at the ends. They do nothing when there are no matches.
* `goToMatch(matchId)` activates the match with the given id and scrolls to it. It does nothing when no match has that id, such as one read before an edit removed it.

## Behavior [#behavior]

* The matches follow the document: edits, undo, and redo update them, and the active match stays on its occurrence.
* `matches` is a new array only when the list changes, and an unchanged match keeps its object, so a results list can memoize its rows by match.
* A match id comes from its paragraph and its position among the paragraph's matches. An edit that adds or removes an earlier match in the same paragraph moves the id to a neighboring match.

## Highlight styling [#highlight-styling]

The SDK paints the matches inside the page text. Style them through the `searchMatch` key of the `theme` prop on [PdfProviders](https://sdk.pdf.net/docs/v1/reference/PdfProviders), or through the CSS variables on the viewport:

| CSS variable                       | Default                   | What it colors    |
| ---------------------------------- | ------------------------- | ----------------- |
| `--search-match-background`        | `rgba(255, 213, 0, 0.4)`  | Every match.      |
| `--search-match-active-background` | `rgba(255, 149, 0, 0.55)` | The active match. |

* A `classNames.searchMatch` class styles the active match apart with a `[data-active]` selector.
* A `styles.searchMatch` entry is written to the element as is: give lengths units (`'4px'`, not `4`).
* Use paint properties only, such as `background` and `color`: a padding, margin, or border moves the document text.

## Example [#example]

```tsx
import { useDocumentSearch } from '@sdk-pdf/react'

function SearchBar() {
  const {
    criteria,
    matches,
    activeMatchIndex,
    status,
    setSearchCriteria,
    goToNextMatch,
    goToPreviousMatch,
  } = useDocumentSearch()

  return (
    <div>
      <input
        value={criteria.query}
        placeholder="Search"
        onChange={(event) =>
          setSearchCriteria({ ...criteria, query: event.target.value })
        }
        onKeyDown={(event) => {
          if (event.key === 'Enter')
            (event.shiftKey ? goToPreviousMatch : goToNextMatch)()
        }}
      />
      <label>
        <input
          type="checkbox"
          checked={criteria.isCaseSensitive}
          onChange={(event) =>
            setSearchCriteria({ ...criteria, isCaseSensitive: event.target.checked })
          }
        />
        Match case
      </label>
      <span>
        {matches.length > 0
          ? `${activeMatchIndex + 1} of ${matches.length}`
          : status === 'complete'
            ? 'No results'
            : ''}
      </span>
    </div>
  )
}
```

See also [useScrollToBlock](https://sdk.pdf.net/docs/v1/reference/useScrollToBlock) and [Theming and customization](https://sdk.pdf.net/docs/v1/guides/theming-and-customization).

