<!-- GENERATED by scripts/build-llms.mjs from llms/viewers.md — do not edit this file. -->

# `lr-pptx-viewer`

- **Import** `import '@aceshooting/lyra-ui/components/lr-pptx-viewer.js';` (stable tag alias; registers the tag)
- **Class** `LyraPptxViewer`, also available unregistered from `@aceshooting/lyra-ui/components/viewers/pptx-viewer/pptx-viewer.class.js`
- **Family** `components/viewers/` — see `llms/index.md` for its siblings
- **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
- **Release history** [CHANGELOG.md](../../CHANGELOG.md)
- **Deprecations** none
- **Optional peers** `@aiden0z/pptx-renderer` — see `llms/peers.md`
- **Themeable via** 13 parts, 1 custom property — see this component's own `@csspart`/`@cssprop` list below
- **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`

---

## `lr-pptx-viewer`

Best-effort client-side PPTX viewer backed by the optional `@aiden0z/pptx-renderer` peer. A
localized fidelity notice is always visible because animations, equations, embedded objects,
speaker notes, and several advanced effects are not rendered.

**Properties:** `src: string = ''`, `name: string = ''`, `label?: string`, `page: number = 1`
(reflected, one-based current slide), and `maxHeight: string = ''` (attribute `max-height`). Assigning
`page` while ready navigates to that slide. Omitting `label` reads back `undefined` and falls back to
`name`, then a localized default; an explicit empty string clears it. A host
`aria-label` takes precedence over
`label` and `name`. `maxHeight` caps the scrollable `[part="container"]`; invalid CSS `max-height`
values, declaration breaks, and `url()` are ignored. `highlights`, `activeHighlightId`, `anchor`,
and `anchorKinds`
(`['text-quote', 'fragment']`) provide the shared text-viewer contract when the renderer exposes
DOM text. Lyra defines no fragment ids for slides. A fragment can resolve only an exact DOM `id`
exposed by the optional renderer in its currently mounted output; renderer-owned ids are not a
stable Lyra navigation contract. Use `page`/`goToSlide()` or a text-quote anchor instead.

**Methods:** `goToSlide(index)` returns a promise and navigates the mounted presentation using the
renderer's zero-based index. A current renderer rejection is contained, enters the localized error
state, emits `lr-render-error`, and does not escape as an unhandled promise rejection.
`renderPageThumbnailToContainer(page, container, options?)` renders a
one-based, width-bounded DOM/SVG slide preview and resolves to a caller-owned disposable handle (or
`false` when unavailable/invalid); it generation-checks asynchronous preview resources after they
settle.
`search(query)` searches the renderer's complete presentation model, not its windowed DOM, retains
at most 10,000 validated results, navigates the matching slide, and paints a renderer-owned node
overlay. Queries are capped at 4,096 code units and one result-validation pass at 4,000,000 code
units; a truncated pass reports `matchCountExact: false`. `searchNext()`, `searchPrevious()`, and `clearSearch()` navigate/dispose those model
results. `scrollToAnchor()` remains available for renderer output that exposes DOM text.

**Events:**

- `lr-load` — `detail: { slideCount }` — fired after a presentation opens.
- `lr-slide-change` — `detail: { index, count }` — fired when the active slide changes.
- `lr-page-viewer-state-change` — `detail.snapshot` is the same atomic readonly value exposed by
  `pageViewerSnapshot`: `{ identity, status, page, pageCount }`. `identity` changes at the start of
  every load so a rail can discard same-count replacement thumbnails without inferring identity
  from `src`.
- `lr-render-error` with `detail.error` when fetching/opening fails, public slide navigation rejects,
  or a post-load peer event is explicitly classified fatal.
- `lr-viewer-diagnostic` — `detail.diagnostic` is a readonly structured slide/node/search
  diagnostic with stable `code`, `severity`, `fatal`, `source`, `cause`, and correlated `page` or
  `nodeId` when valid. Recoverable events keep the mounted deck usable and do not also emit
  `lr-render-error`; fatal events enter the localized error state, destroy the adapter, and emit the
  terminal event once.
- `lr-search-change` — `detail: { query: string; matchCount: number; matchCountExact: boolean; activeIndex: number }` — fired
  whenever rendered-presentation search state changes, including canonical source reset and
  effective-locale re-evaluation.
- `lr-anchor-result` — `detail: { found: boolean }` — fired after an `anchor` assignment or
  `scrollToAnchor()` call is applied.
- `lr-text-select` — `detail: TextSelectDetail` (`{ text: string; anchor: LyraAnchor | null; rects:
DOMRect[] }`) — fired after a selection ends inside the rendered presentation.

`lr-highlight-activate` is not part of this viewer's event contract: painted renderer-text
highlights are passive and cannot be activated.

The three shared text-viewer events bubble and compose and are non-cancelable.

**CSS parts:** `base` (the named region with explicit `aria-busy="true"|"false"`), `header`, `name`,
`notice`, `error`, `nav`, `previous-button`, `previous-icon`, `slide-count`, `next-button`,
`next-icon`, `container`, and `anchor-live-region` (an aria-hidden, non-live shadow mirror of the
latest anchor-jump message; the spoken copy is appended to the shared document-level polite sink
only while the viewer and its composed ancestors are exposed to the accessibility tree). While
loading, the decorative skeleton is paired with an ordinary visually-hidden localized label; later
loading and error transitions use the shared document-level polite and assertive sinks,
respectively, without adding live semantics inside the viewer shadow. The previous/next chevrons
mirror under effective RTL direction, including inherited `dir` changes.

**Themeable custom properties:** `--lr-pptx-viewer-max-height` (default `none`) — maximum block
size of `[part="container"]` before it scrolls internally; also settable via the `max-height`
property, which writes this token inline.

**Optional peer dependency:** install `@aiden0z/pptx-renderer` with
`pnpm add @aiden0z/pptx-renderer`. The registry matches the official PPTX MIME type and `.pptx`
filenames, declaring `{ anchors: ['text-quote', 'fragment'], search: true, textSelect: true }`
capabilities and forwarding `anchor`/`highlights` to the mounted viewer. That forwarding preserves
the request across the registry hop; it does not create stable fragment ids in renderer output.

Importing `pptx-viewer.js` (this component's own registration entry) loads `<lr-pptx-viewer>`'s
class module immediately. A granular consumer (not importing the `all.js` compatibility bundle) who
wants that deferred too can instead import
`@aceshooting/lyra-ui/components/viewers/pptx-viewer/pptx-viewer-register.js`, which installs the
same registration lazily and exports `PPTX_VIEWER_TAG` (`'lr-pptx-viewer'`) as a stable reference to
the tag it eventually registers.

Remote resources are capped at 25 MB and measured ZIP expansion is capped at 256 MB before the
renderer opens the archive; exceeding either ceiling surfaces the localized
`documentPreviewResourceTooLarge` message instead of the presentation. The optional peer must also
expose its complete recommended ZIP-limits capability within Lyra's safety ceilings. Missing,
malformed, or more-permissive limits make the peer unavailable and the viewer fails closed.

The peer instance is immediately wrapped in a validated `PptxViewerAdapter`; the component observes
only readonly slide metadata, complete-model search/navigation/highlight/thumbnail capabilities and
normalized correlated events. Raw renderer DOM windowing and event payloads do not become component
state.
`PptxViewerAdapter`, `PptxViewerAdapterEvent`, `PptxTextSearchResult`, and
`PptxSearchHighlightHandle`/`PptxThumbnailHandle` are exported from the granular PPTX loader module.
The shared diagnostic
types are `LyraViewerDiagnostic`, `LyraViewerDiagnosticCode`, `LyraViewerDiagnosticSeverity`, and
`LyraViewerDiagnosticEventDetail`.
