import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraClipboardWriteFailure,LyraClipboardWriteSuccess}from'../../../internal/clipboard.js';import{type ShikiLanguageInput}from'./code-loader.js';import type{LyraCodeBlockCopyAppearance}from'./code-block-shared.js';import type{LyraAnchor,LyraHighlight,TextSelectRect}from'../../viewers/document-viewer/anchors.js';import'../../overlays/skeleton/skeleton.class.js';export interface LyraCodeBlockEventMap{'lr-copy':CustomEvent;'lr-error':CustomEvent;'lr-copy-error':CustomEvent;'lr-toggle-request':CustomEvent<{collapsed:boolean;}>;'lr-toggle':CustomEvent<{collapsed:boolean;}>;'lr-line-activate':CustomEvent<{line:number;}>;'lr-text-select':CustomEvent<{readonly text:string;readonly anchor:LyraAnchor;readonly rects:readonly TextSelectRect[];}>;} /** * `` — fenced code display with optional lazy syntax * highlighting and a copy button. No highlighting grammar ships in this * component itself: it lazy-loads the optional peer dependency `shiki` (see * `code-loader.ts`) for the actual tokenizing, and degrades to a plain * `
` when that peer isn't installed or `language` is unset/
* unrecognized — the exact same optional-peer shape `` and
* `` already establish. That fallback is the *default* rendering
* path, not a degraded one: unhighlighted code is perfectly usable, and it's
* what every instance renders at zero extra bytes until shiki resolves.
*
* A `` placeholder stands in only while shiki itself is
* loading for the very first time on the page (cached — see
* `loadShikiHighlighter()`) and `language` is set. It's deliberately *not*
* shown again for a subsequent per-language grammar load (e.g. a second
* `` requesting a language no earlier instance has used
* yet) — that grammar fetch is typically fast, and the plain-text fallback
* is already a perfectly readable placeholder for it, so a second
* loading-chrome state would add complexity for little practical benefit.
*
* Set a host `aria-label` (or the matching `accessibleLabel` property) to
* override the filename/language-derived name on the internal focusable code
* region. The name is forwarded to the element that owns `role="group"`, not
* left only on the custom-element host across the shadow boundary.
*
* `languages` is an additive, opt-in escape hatch from that default path for
* a consumer whose language set is fixed and known ahead of time: a map of
* language id to an already-imported shiki grammar module (e.g. `import bash
* from 'shiki/langs/bash.mjs'`). When `language` matches a key in `languages`,
* this component seeds a fine-grained `createHighlighterCore()` highlighter
* with *only* the pre-supplied grammars (see `code-loader.ts`'s
* `loadShikiHighlighterCore()`) instead of waiting on `loadShikiHighlighter()`
* and its dynamic per-language `loadLanguage()` import. The payoff isn't
* runtime cost — the default dynamic-import path is already well-optimized
* for that — it's *build output*: shiki's main entry point bundles a dynamic
* `import()` per bundled language (~200 of them) because a bundler can't
* statically narrow which of those a `loadLanguage(lang: string)` call might
* request at runtime, so it conservatively emits a build-output chunk for
* every one of them. `shiki/core`'s fine-grained API has no such table — a
* bundler only ever sees the exact grammar modules `languages` itself
* `import`s, so a consumer who pins its full language set this way trades a
* hand-maintained list for a build output scoped to just those languages
* instead of shiki's entire bundled set. A language requested but absent
* from `languages` still falls back to the ordinary dynamic-import path
* unchanged, so this is a partial opt-in, not a replacement for it.
*
* Adopts the `line-range` slice of this library's shared anchor-target contract:
* `highlights`/`activeHighlightId` paint (and `highlight-lines` additionally marks) per-line
* emphasis in both the shiki and plain-text-fallback rendering paths identically, and
* `scrollToAnchor()` resolves a `line-range` anchor. `activatable-lines` is a separate, purely
* local affordance that turns the (`line-numbers`-gated) gutter into a keyboard-navigable,
* clickable roving-tabindex group emitting `lr-line-activate` — it doesn't require `highlights` to
* be set. If controlled `code` shrinks while a line owns focus, focus follows the clamped
* surviving line through both plain and highlighted DOM replacement; an explicit move to another
* control during the update is never overridden.
*
* @customElement lr-code-block
* @event lr-copy - The raw `code` was written to the clipboard. Frozen detail:
*   `{ ok: true, text }`.
* @event lr-error - Clipboard writing failed; generic no-detail notification.
* @event lr-copy-error - Clipboard writing failed. Frozen detail:
*   `{ ok: false, text, reason, error }`, where `reason` is
*   `'unsupported' | 'denied' | 'failed'`.
* @event lr-toggle-request - Cancelable request emitted before collapse state changes.
*   `detail: { collapsed }` is the proposed next state.
* @event lr-toggle - The collapse/expand header button was activated.
*   `detail: { collapsed }` — same event name and shape convention as
*   ``'s own `lr-toggle`.
* @event lr-line-activate - A gutter line number was activated (click, or Enter/Space while
*   focused) while `activatable-lines` is set. `detail: { line }`.
* @event lr-text-select - Fired when a text selection inside the code body ends. `detail: {
*   text, anchor, rects }`; `anchor` is a `line-range` anchor covering the selected lines.
* @csspart base - The outer container.
* @csspart header - The row above the code (filename/language/copy/toggle),
*   present whenever there's anything to put in it.
* @csspart filename - The `filename` text, when set.
* @csspart language - The `language` badge, when set, so the language is
*   exposed to assistive tech as visible text rather than only a `language`
*   attribute a screen reader would never announce.
* @csspart copy-button - The copy-to-clipboard control, when `copyable`. A composed
*   `` as of 16.0.0: it still owns the accessible name, the activation and the part
*   names, while its background, radius, hover/press mixes, focus ring and hit-area floor now come
*   from `--lr-icon-button-*`. Also carries `copy-button-text` or `copy-button-icon` for the active
*   `copyAppearance`, since a state cannot be selected with `::part(copy-button)[attr]`.
* @csspart copy-button-text - The copy control while `copyAppearance` is `'text'`.
* @csspart copy-button-icon - The copy control while `copyAppearance` is `'icon'`.
* @csspart copy-button__control - The copy control's own native `