> ## Documentation Index
> Fetch the complete documentation index at: https://mahmoud-b28887f9.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# rememberPdfViewerState: Compose viewer state factory

> rememberPdfViewerState creates a KPdfViewerState, wires platform save and open flows, and disposes the state when the composable leaves the composition.

`rememberPdfViewerState` is the recommended entry point for integrating KPDF into a Compose Multiplatform screen. It constructs a `KPdfViewerState` via `KPdfFactory.create()`, binds the three platform-native side-effect handlers for document open, save, and external-open flows, triggers an initial `open()` call for the given source, and disposes the state cleanly when the composable leaves the composition. Calling this function once is all you need before passing the returned state to `KPdfViewer`, `KPdfViewerToolbar`, and `KPdfThumbnailStrip`.

## Signature

```kotlin theme={null}
@Composable
fun rememberPdfViewerState(
    source: KPdfSource,
    config: KPdfViewerConfig = KPdfViewerConfig.builder().build(),
): KPdfViewerState
```

## Parameters

<ParamField path="source" type="KPdfSource" required>
  Describes where the PDF comes from. Supported subtypes are:

  * `KPdfSource.Url(url: String, headers: Map<String, String> = emptyMap())` — fetches from a remote URL, with optional HTTP headers.
  * `KPdfSource.Bytes(bytes: ByteArray)` — loads from in-memory bytes.
  * `KPdfSource.Base64(base64: String)` — decodes a Base64-encoded PDF string.

  The state is keyed on `source` inside `remember(source, config, sdk) { … }`. Providing a new `source` instance that is not equal to the previous one causes the SDK to create a new viewer state and immediately call `open()` on the new source. Keep `source` stable across recompositions — see the stability warning below.
</ParamField>

<ParamField path="config" type="KPdfViewerConfig">
  Controls runtime viewer behaviour. Defaults to `KPdfViewerConfig.builder().build()` which applies all SDK defaults. Build a custom config with the builder:

  ```kotlin theme={null}
  KPdfViewerConfig.builder()
      .enableZoom(true)
      .enableSwipe(true)
      .zoomRange(minZoom = 1f, maxZoom = 5f)
      .doubleTapZoom(2f)
      .ramCacheSize(6)
      .diskCacheSize(24)
      .preloadPageCount(2)
      .build()
  ```

  Like `source`, `config` is a `remember` key. Rebuilding a new `KPdfViewerConfig` inline on every recomposition recreates the entire viewer state. Wrap it in `remember { … }` or hoist it to a stable scope.
</ParamField>

## Return value

Returns a `KPdfViewerState` instance that is remembered for the lifetime of the composable and disposed when it leaves the composition. Pass it to connected views:

```kotlin theme={null}
KPdfViewer(state = viewerState)
KPdfViewerToolbar(state = viewerState, …)
KPdfThumbnailStrip(state = viewerState, …)
```

## What the function does internally

1. **Creates the SDK facade** — `KPdfFactory.create()` is called once and remembered independently of `source` and `config`.
2. **Creates the viewer state** — `sdk.viewerState(source, config)` is called inside `remember(source, config, sdk)`. A new state is produced only when `source` or `config` changes.
3. **Opens the document** — A `LaunchedEffect(state, source)` calls `state.open(source)` on the IO dispatcher.
4. **Binds platform effects** — Platform-native file-picker and intent callbacks are registered automatically for save, open, and external-open flows on Android and iOS.
5. **Disposes on leave** — `state.close()` is called when the composable leaves the composition, releasing all resources including cached pages.

## Usage

```kotlin theme={null}
@Composable
fun PdfScreen(source: KPdfSource) {
    // Keep source stable — wrap in remember if it might be rebuilt upstream
    val stableSource = remember(source) { source }

    val viewerConfig = remember {
        KPdfViewerConfig.builder()
            .zoomRange(minZoom = 1f, maxZoom = 5f)
            .doubleTapZoom(2f)
            .ramCacheSize(6)
            .diskCacheSize(24)
            .preloadPageCount(2)
            .build()
    }

    val viewerState = rememberPdfViewerState(
        source = stableSource,
        config = viewerConfig,
    )

    KPdfViewer(
        state = viewerState,
        modifier = Modifier.fillMaxSize(),
    )
}
```

<Warning>
  `source` and `config` are `remember` keys. If either value is reconstructed on every recomposition — for example, a `KPdfSource.Url(...)` call or a `KPdfViewerConfig.builder().build()` call written directly inside the composable body — `rememberPdfViewerState` creates a new `KPdfViewerState` on every frame. This resets all observable states including `openDocumentState`, `saveState`, and `externalOpenState`, and cancels any in-flight platform picker session.

  Always compute `source` and `config` inside `remember { … }` or hoist them to a ViewModel before passing them to `rememberPdfViewerState`.
</Warning>

## Manual state creation

If you need to manage the viewer lifecycle yourself — for example inside a custom ViewModel or outside of Compose — create the state directly:

```kotlin theme={null}
val sdk = KPdfFactory.create()
val viewerState = sdk.viewerState(
    source = KPdfSource.Url("https://example.com/file.pdf"),
    config = KPdfViewerConfig.builder().build(),
)

// Open the document
viewerState.open(source)

// Release resources when done
viewerState.close()
```

When creating the state manually you are responsible for calling `open()`, binding any platform effects, and calling `close()` at the appropriate lifecycle point.

## Notes

* You should use one `KPdfViewerState` per visible viewer instance. Do not share a single state between two simultaneously visible `KPdfViewer` composables.
* `KPdfViewer`, `KPdfViewerToolbar`, and `KPdfThumbnailStrip` all read from the same `KPdfViewerState`, so you only call `rememberPdfViewerState` once per screen.
* `state.close()` is idempotent — calling it more than once is safe and has no effect after the first call.
