import * as _angular_core from '@angular/core';
import { ElementRef, AfterViewInit, OnDestroy, InjectionToken } from '@angular/core';
import { Api } from 'chessground/api';
import { Config } from 'chessground/config';
import { Key, Color } from 'chessground/types';
export { Key } from 'chessground/types';
import { MatDialogRef } from '@angular/material/dialog';
import { Chess } from 'chess.js';
/**
* Core chessboard component wrapping the chessground library via snabbdom.
*
* Accepts a `runFunction` signal-model input that receives the mounted DOM element
* and must return a chessground `Api` instance. The component manages lifecycle:
* - Uses an Angular `afterRenderEffect()` to watch both `runFunction` changes
* and `viewChild` population, redrawing the board after Angular finishes DOM
* rendering. This is the recommended approach for third-party library integration.
* - When the `runFunction` identity changes, the previous Chessground instance
* is destroyed before the new one is created.
* - Provides an optional `config` input: when its identity changes, the config
* is applied to the **existing** instance in place via `Api.set()`. This keeps
* animations and drag & drop state intact and is far cheaper than recreating
* the instance — the preferred way to update positions/moves.
* - Provides a `toggleOrientation()` method to flip the board.
*
* Uses {@link NgxChessgroundService} (provided at component level) for snabbdom patching
* and chessground instance management.
*
* @example
* ```html
*
* ```
*
* @example
* ```typescript
* myRunFn = signal<(el: HTMLElement) => Api>((el) => {
* return Chessground(el, { fen: 'start' });
* });
* ```
*/
declare class NgxChessgroundComponent {
/**
* Signal-based view query for the board container element.
*
* References the DOM element with template variable `#chessboard`.
* Tracked by `afterRenderEffect` to pass the native element to chessground.
*/
readonly elementView: _angular_core.Signal>;
/**
* Function that constructs the chessground instance on a given element.
*
* This is the primary input mechanism of the component, and it is
* **required** — omitting it is a compile-time error rather than a silently
* blank board. Changes to the function's identity trigger a board redraw
* via `afterRenderEffect()`; the previous instance is destroyed first.
*
* A plain `input()` (not a `model()`) because a callback is never written
* back to by the component — there is no two-way binding to expose.
*
* @param el — The board container `HTMLElement` mounted in the DOM.
* @returns A chessground `Api` instance configured as desired.
*/
readonly runFunction: _angular_core.InputSignal<(el: HTMLElement) => Api>;
/**
* Optional partial Chessground config applied to the live instance via
* `Api.set()` whenever its identity changes.
*
* Prefer updating the board through this input instead of changing
* `runFunction`: the instance is reconfigured in place, preserving
* animations, drag & drop state and avoiding recreation costs.
*/
readonly config: _angular_core.InputSignal | null>;
/** Service managing the chessground instance and snabbdom patching lifecycle. */
private readonly ngxChessgroundService;
/** Last run function applied, used to skip redundant instance recreation. */
private lastFn;
/** Last config applied, used to skip redundant set() calls. */
private lastConfig;
/**
* Sets up an `afterRenderEffect` that redraws the chessboard after Angular
* finishes rendering the DOM.
*
* Uses the recommended phase separation:
* - **earlyRead** — reads signals to establish reactive tracking
* - **write** — performs DOM manipulation (snabbdom patching) with the
* guarantee that Angular's rendering is complete
*
* `afterRenderEffect` is the correct API for third-party library
* integration per Angular's guidance. Standard `effect` runs before
* Angular updates the DOM, which can cause timing issues with
* `viewChild` signals and DOM-dependent libraries.
*/
constructor();
/**
* Flips the board orientation (white ↔ black).
*
* Delegates to {@link NgxChessgroundService.toggleOrientation}.
*/
toggleOrientation(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* A table-style chessboard demo component.
*
* Displays a single chessboard initialized with the "Play legal moves from initial position"
* unit preset, enhanced with dialog-based pawn promotion via {@link PromotionService}.
*
* The run function is exposed as a `computed`, so the child board receives it
* directly through its required `runFunction` input — no view-child query, no
* imperative `effect()`, and no `initialized` guard flag.
*
* @example
* ```html
*
* ```
*/
declare class NgxChessgroundTableComponent {
/** Injected promotion dialog service for pawn promotion UX. */
private readonly promotionService;
/**
* Board factory for the "play from the initial position" preset, wired to
* the promotion dialog.
*
* The identity is stable: `createPlayUnitsWithDialog` returns fresh unit
* objects only when re-evaluated, and a `computed` caches its result until a
* dependency changes. The board therefore is not torn down and recreated.
*/
protected readonly runFunction: _angular_core.Signal<(el: HTMLElement) => Api>;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* A single segment of highlighted text — either a matching portion or
* non-matching surrounding text.
*/
interface TextSegment {
/** The substring of the original text. */
text: string;
/** Whether this segment matched the search query. */
match: boolean;
}
/**
* Splits `text` into match / non-match segments for typeahead highlighting.
*
* Performs a case-insensitive substring match of `query` within `text`.
* Returns an array of {@link TextSegment} objects that can be rendered
* with conditional styling (e.g. bold for matching segments).
*
* @param text — Full text to segment (e.g. a player name).
* @param query — Search query string to match against.
* @returns Array of `{ text, match }` objects for template rendering.
*
* @example
* ```typescript
* const segments = highlightMatch('GM Magnus Carlsen (2850)', 'carl');
* // [
* // { text: 'GM Magnus ', match: false },
* // { text: 'Carl', match: true },
* // { text: 'sen (2850)', match: false },
* // ]
* ```
*/
declare function highlightMatch(text: string, query: string): TextSegment[];
/**
* Types for the PGN viewer component and its sub-components.
*/
/** Collapsible section identifier for the left panel. */
type LeftPanelSection = 'players' | 'gameDetails' | 'upsets' | 'rating' | 'position';
/** Collapsible section identifier for the right panel. */
type RightPanelSection = 'moves' | 'replay' | 'loadCache';
/** Replay timing mode. */
type ReplayMode = 'realtime' | 'proportional' | 'fixed' | 'fast';
/** Which side's errors should trigger "stop on error" during replay. */
type StopOnErrorSide = 'both' | 'white' | 'black';
/** Player name with optional selection state for typeahead. */
interface PlayerSuggestion {
/** Display name of the player. */
name: string;
/** Whether this suggestion is the highlighted one in the dropdown. */
active: boolean;
}
/** A single evaluation change representing a "stop on error" event. */
interface EvaluationChange {
/** Zero-based index of the move that caused the change. */
moveIndex: number;
/** Size of the evaluation swing, in pawns. */
diff: number;
/** The configured `stopOnErrorThreshold` this `diff` exceeded. */
threshold: number;
/** Side whose move caused the evaluation change. */
side: 'white' | 'black';
}
/** Clock state at a given half-move. */
interface ClockState {
/** Remaining time for White, in seconds. */
white: number;
/** Remaining time for Black, in seconds. */
black: number;
}
/** Stockfish analysis result. */
interface BestMoveInfo {
/** Best move found, in SAN. */
move: string;
/** Principal variation, as SAN plus the FEN reached after each move. */
pv: {
san: string;
fen: string;
}[];
/**
* Engine evaluation of the position, from White's perspective
* (e.g. `'+0.32'`, `'#-2'`).
*/
score?: string;
}
/** A single move played during practice mode. */
interface PracticeMove {
/** Move in standard algebraic notation (SAN). */
san: string;
/**
* Stockfish evaluation of the position after this move, from White's
* perspective (e.g. `'+0.32'`, `'#-2'`), or null while pending/unknown.
*/
evaluation: string | null;
}
/** Complete export payload for a practice session. */
interface PracticeExport {
/** FEN of the position where the practice session started. */
startFen: string;
/** FEN of the current practice position. */
fen: string;
/** SAN moves played during the practice session. */
moves: string[];
/** Formatted move text (e.g. `"1. e4 e5 2. Nf3"`). */
moveText: string;
/** Full PGN of the practice session, including evaluation comments. */
pgn: string;
}
/** Game metadata for the filter panel's game list. */
interface FilterGameInfo {
/** One-based game number as shown in the list. */
number: number;
/** Player with the white pieces. */
white: string;
/** Player with the black pieces. */
black: string;
/** Result string: `'1-0'`, `'0-1'`, `'1/2-1/2'` or `'*'`. */
result: string;
}
/** Typeahead keyboard navigation handler. */
interface TypeaheadKeyboardEvent {
/** The `KeyboardEvent.key` value that was pressed. */
key: string;
/** Suppresses the browser's default handling of the key. */
preventDefault(): void;
}
/** Input/output contract for the player typeahead component. */
interface PlayerTypeaheadState {
/** Current text in the typeahead field. */
value: string;
/** Player names matching the current query. */
suggestions: string[];
/** Whether the suggestion dropdown is showing. */
isOpen: boolean;
/** Index of the highlighted suggestion, or `-1` when none is highlighted. */
activeIndex: number;
}
/**
* A PGN data source the viewer can load.
*
* A discriminated union rather than a set of boolean flags, so an invalid
* combination ("load a URL and also this file") is unrepresentable.
*/
type PgnSource =
/** A remote archive or PGN file. `.zst` is decompressed automatically. */
{
readonly kind: 'url';
/** Absolute or app-relative URL. */
readonly url: string;
/**
* Remember this URL alongside the content hash so a later session
* can restore it from cache without downloading. Defaults to the
* URL itself, or `false` to opt out of bookmarking.
*/
readonly cacheAs?: string | false;
}
/** Raw PGN text already held by the host. */
| {
readonly kind: 'pgn';
readonly text: string;
/** Optional origin, used for cache bookmarking. */
readonly sourceUrl?: string;
}
/** A `File` from an `` or drag & drop. */
| {
readonly kind: 'file';
readonly file: File;
};
/** Optional per-call overrides for {@link PgnSource} loading. */
interface LoadOptions {
/**
* Build a position index for the loaded games. Defaults to the viewer's
* current `indexStartPositions` setting.
*/
readonly indexStartPositions?: boolean;
/** Max half-moves replayed per game when indexing. Defaults to `maxFenPlies`. */
readonly maxFenPlies?: number;
}
/** Machine-readable failure categories reported through `loadFailed`. */
type PgnViewerErrorCode =
/** The source could not be fetched (network, HTTP status, CORS). */
'DOWNLOAD_FAILED'
/** The archive or PGN text could not be parsed into games. */
| 'PARSE_FAILED'
/** The local cache could not be read or written. */
| 'CACHE_FAILED'
/** The Stockfish worker could not be started. */
| 'ENGINE_FAILED'
/** The source was rejected before any work started (missing/empty input). */
| 'INVALID_SOURCE';
/**
* A failure the host can observe and react to.
*
* Every load path reports exactly one of these on failure, so a host needs a
* single handler rather than sniffing console output.
*/
interface PgnViewerError {
/** Stable category for programmatic branching. */
readonly code: PgnViewerErrorCode;
/** Human-readable description, safe to display. */
readonly message: string;
/** The originating error, when there was one. */
readonly cause?: unknown;
}
/**
* Board display panel for the PGN viewer — center panel.
*
* Shows the chessboard with player names, clocks, turn indicators,
* evaluation bar, board control buttons (flip, 3D toggle),
* Stockfish analysis controls, and move navigation buttons.
*
* All state is owned by the parent container and passed via inputs.
* The component emits events for user interactions.
*/
declare class BoardDisplayComponent {
/**
* Chessground run function for rendering the board.
*
* Required and never `undefined`: the wrapper's `runFunction` input is
* required, so a missing factory is a compile-time error rather than a
* silently empty board.
*/
readonly runFunction: _angular_core.InputSignal<(el: HTMLElement) => Api>;
/**
* Partial Chessground config applied to the live board instance via
* `Api.set()` on every change (position, orientation, movable pieces).
*/
readonly config: _angular_core.InputSignal | null>;
/** Whether the board is flipped (black at bottom). */
readonly flipped: _angular_core.ModelSignal;
/** Whether to render 3D Staunton pieces. */
readonly in3d: _angular_core.ModelSignal;
/** Player shown above the board (Black when unflipped). */
readonly topPlayerName: _angular_core.InputSignal;
/** Player shown below the board (White when unflipped). */
readonly bottomPlayerName: _angular_core.InputSignal;
/** Extra CSS class for the top player row, e.g. a turn indicator. */
readonly topPlayerTurnClass: _angular_core.InputSignal;
/** Extra CSS class for the bottom player row, e.g. a turn indicator. */
readonly bottomPlayerTurnClass: _angular_core.InputSignal;
/** Side to move, as used by chessground's piece theming. */
readonly activeColor: _angular_core.InputSignal;
/** Colour of the top player's piece icon. */
readonly topPlayerActiveColor: _angular_core.InputSignal;
/** Colour of the bottom player's piece icon. */
readonly bottomPlayerActiveColor: _angular_core.InputSignal;
/** Title (GM/IM/…) prefix for the top player, or `''`. */
readonly topPlayerTitle: _angular_core.InputSignal;
/** Title (GM/IM/…) prefix for the bottom player, or `''`. */
readonly bottomPlayerTitle: _angular_core.InputSignal;
/** Formatted remaining time for the top player, or `''` when unknown. */
readonly topTimeRemaining: _angular_core.InputSignal;
/** Formatted remaining time for the bottom player, or `''` when unknown. */
readonly bottomTimeRemaining: _angular_core.InputSignal;
/** Result of the loaded game: `'1-0'`, `'0-1'`, `'1/2-1/2'` or `'*'`. */
readonly gameResult: _angular_core.InputSignal;
/** Whether the board shows the final position of the game. */
readonly isEndOfReplay: _angular_core.InputSignalWithTransform;
/** Evaluation to display, in the viewer's display format, or `null`. */
readonly evaluation: _angular_core.InputSignal;
/** Zero-based index of the displayed move; `-1` is the start position. */
readonly currentMoveIndex: _angular_core.InputSignal;
/** Total number of moves in the loaded game. */
readonly movesCount: _angular_core.InputSignal;
/** Whether the "jump to start" control is enabled. */
readonly canGoFirst: _angular_core.Signal;
/** Whether the "previous move" control is enabled. */
readonly canGoPrev: _angular_core.Signal;
/** Whether the "next move" control is enabled. */
readonly canGoNext: _angular_core.Signal;
/** Whether the "jump to end" control is enabled. */
readonly canGoLast: _angular_core.Signal;
/** Whether Stockfish is analyzing the displayed position. */
readonly isAnalyzing: _angular_core.InputSignalWithTransform;
/** Engine best move and principal variation, or `null`. */
readonly bestMoveInfo: _angular_core.InputSignal;
/** Whether the analysis panel is expanded. */
readonly analysisVisible: _angular_core.InputSignalWithTransform;
/** Whether the "show better move" button should be offered. */
readonly showBetterMoveBtn: _angular_core.InputSignalWithTransform;
/** Stockfish search depth (two-way). */
readonly stockfishDepth: _angular_core.ModelSignal;
/** Whether there is a next alternative move to cycle to. */
readonly hasNextAlternative: _angular_core.InputSignalWithTransform;
/** Whether there is a previous alternative to cycle back to. */
readonly hasPrevAlternative: _angular_core.InputSignalWithTransform;
/** Label showing current alternative position (e.g. "2/3"). */
readonly alternativeLabel: _angular_core.InputSignal;
/** Whether autoplay of the best line has completed (enables re-evaluate). */
readonly autoplayCompleted: _angular_core.InputSignalWithTransform;
/** Whether the "Analyze practice" button should be offered (game not replaying). */
readonly practiceAvailable: _angular_core.InputSignalWithTransform;
/** Whether practice mode is currently active. */
readonly practiceActive: _angular_core.InputSignalWithTransform;
/** The user asked to flip the board orientation. */
readonly flipBoard: _angular_core.OutputEmitterRef;
/** The user asked to toggle 3D pieces. */
readonly toggle3d: _angular_core.OutputEmitterRef;
/** The user asked to jump to the start of the game. */
readonly goToStart: _angular_core.OutputEmitterRef;
/** The user asked to step back one move. */
readonly prev: _angular_core.OutputEmitterRef;
/** The user asked to step forward one move. */
readonly next: _angular_core.OutputEmitterRef;
/** The user asked to jump to the end of the game. */
readonly end: _angular_core.OutputEmitterRef;
/** The user asked to analyze a position; emits its FEN. */
readonly analyzePosition: _angular_core.OutputEmitterRef;
/** The user asked to autoplay the engine's best line. */
readonly autoplayBestLine: _angular_core.OutputEmitterRef;
/** The user asked to preview a principal-variation move; emits its FEN. */
readonly previewPvMove: _angular_core.OutputEmitterRef;
/** The user asked to show or hide the analysis panel. */
readonly toggleAnalysis: _angular_core.OutputEmitterRef;
/** Cycle to the next-best engine move. */
readonly nextBestMove: _angular_core.OutputEmitterRef;
/** Cycle to the previous engine move. */
readonly prevBestMove: _angular_core.OutputEmitterRef;
/** Re-evaluate the position currently displayed on the board. */
readonly reevaluate: _angular_core.OutputEmitterRef;
/** Start practice mode from the current board position. */
readonly startPractice: _angular_core.OutputEmitterRef;
/** Applies the Stockfish depth chosen in the number input. */
onStockfishDepthChange(event: Event): void;
/** Forwards an analyze request for the given position. */
onAnalyzePosition(fen: string): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* Vertical evaluation bar showing the current position evaluation.
*
* Displays a white/black gradient bar with a centered divider and
* a floating text badge showing the current centipawn/mate score.
* Supports flipping via CSS scaleY when the board orientation is flipped.
*
* @example
* ```html
*
* ```
*/
declare class EvaluationBarComponent {
/** Raw evaluation string (e.g. `"+1.23"`, `"#3"`, `"-M2"`) or null. */
readonly evaluation: _angular_core.InputSignal;
/** Whether the board is flipped (black at bottom). Flips the bar. */
readonly flipped: _angular_core.InputSignalWithTransform;
/** Height percentage for the fill (0 = all black, 100 = all white, 50 = equal). */
readonly barHeight: _angular_core.Signal;
/** Formatted evaluation string for the text badge (e.g. `"+1.23"`, `"M3"`, `"-M2"`). */
readonly formattedEval: _angular_core.Signal;
/** CSS class for the evaluation fill based on advantage. */
readonly evalClass: _angular_core.Signal<"eval-equal" | "eval-white" | "eval-black">;
/** Dynamic fill color using CSS variables for theme support. */
readonly evalFillColor: _angular_core.Signal<"var(--eval-fill-white, #ffffff)" | "var(--eval-fill-black, #ffffff)" | "var(--eval-fill-equal, #ffffff)">;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* Desktop (Deno) runtime detection.
*
* The packaged desktop app serves the same Angular bundle as the web app, but
* `desktop/server.ts` injects `desktop/desktop-adapter.js` into the page, which
* exposes a `window.__desktop__` marker before the bundle runs.
*
* This matters for persistence: Deno Desktop points the webview at a random
* localhost port on every launch, so the webview origin — and with it
* `localStorage` and `IndexedDB` — is new each time. Only in the desktop
* runtime do the viewer's settings and its parsed-game cache therefore go
* through the local server's on-disk `/api/state` and `/api/cache` endpoints.
* In a regular browser everything keeps using web storage.
*/
/** Shape of the marker object injected by the desktop adapter. */
interface DesktopMarker {
/**
* Opens the host's native file picker.
*
* @param extensions — Allowed file extensions, e.g. `['.pgn', '.zip']`.
* @returns The chosen path, or `null` when the user cancelled.
*/
openFileDialog?(extensions: string[]): Promise;
}
/** Returns `true` when running inside the Deno Desktop webview. */
declare function isDesktopRuntime(): boolean;
/**
* Filter panel for the PGN viewer — left sidebar.
*
* Contains collapsible sections for:
* - Player name typeahead filters (white/black)
* - Game details (result, ECO, time control, event)
* - Rating range filters with presets
* - Position/FEN and opening-move filters
*
* All state is managed by the parent container and passed via inputs/outputs.
* This component is purely presentational.
*/
declare class GameFilterPanelComponent {
/** White-player name filter (two-way). */
readonly filterWhite: _angular_core.ModelSignal;
/** Black-player name filter (two-way). */
readonly filterBlack: _angular_core.ModelSignal;
/** When `true`, a name matches either colour instead of its own field only (two-way). */
readonly ignoreColor: _angular_core.ModelSignal;
/** All distinct White player names, for the typeahead. */
readonly uniqueWhitePlayers: _angular_core.InputSignal;
/** All distinct Black player names, for the typeahead. */
readonly uniqueBlackPlayers: _angular_core.InputSignal;
/** Selected results; an empty array means "no result filter" (two-way). */
readonly filterResult: _angular_core.ModelSignal;
/** Selected ECO code, or `''` for none (two-way). */
readonly filterEco: _angular_core.ModelSignal;
/** Selected time-control keys, e.g. `['180+2']` (two-way). */
readonly filterTimeControl: _angular_core.ModelSignal;
/** Selected event name, or `''` for none (two-way). */
readonly filterEvent: _angular_core.ModelSignal;
/** Selected broadcast name, or `''` for none (two-way). */
readonly filterBroadcastName: _angular_core.ModelSignal;
/** Distinct ECO codes with game counts, for the dropdown. */
readonly sortedEcoCodes: _angular_core.InputSignal<{
code: string;
count: number;
}[]>;
/** Distinct time controls with counts and a human-readable label/originals summary. */
readonly sortedTimeControls: _angular_core.InputSignal<{
key: string;
count: number;
label: string;
originalsSummary: string;
}[]>;
/** Distinct event names with game counts, for the dropdown. */
readonly sortedEvents: _angular_core.InputSignal<{
event: string;
count: number;
}[]>;
/** Distinct broadcast names with game counts, for the dropdown. */
readonly sortedBroadcastNames: _angular_core.InputSignal<{
broadcastName: string;
count: number;
}[]>;
/** Whether upset filtering is enabled (two-way). */
readonly filterUpsetEnabled: _angular_core.ModelSignal;
/** Include upsets won by the lower-rated player (two-way). */
readonly filterUpsetWin: _angular_core.ModelSignal;
/** Include upsets drawn by the lower-rated player (two-way). */
readonly filterUpsetDraw: _angular_core.ModelSignal;
/** Minimum Elo gap between players for a game to count as an upset. */
readonly filterUpsetMinDiff: _angular_core.ModelSignal;
/** Whether rating-range filtering is enabled (two-way). */
readonly filterRatingEnabled: _angular_core.ModelSignal;
/** Lower bound of the White rating range, as entered (two-way). */
readonly filterWhiteRating: _angular_core.ModelSignal;
/** Lower bound of the Black rating range, as entered (two-way). */
readonly filterBlackRating: _angular_core.ModelSignal;
/** Upper bound of the White rating range, as entered (two-way). */
readonly filterWhiteRatingMax: _angular_core.ModelSignal;
/** Upper bound of the Black rating range, as entered (two-way). */
readonly filterBlackRatingMax: _angular_core.ModelSignal;
/** Whether the opening-move prefix filter is active (two-way). */
readonly filterMoves: _angular_core.ModelSignal;
/** Whether position (FEN) filtering is active (two-way). */
readonly filterByFenEnabled: _angular_core.ModelSignal;
/** Target position for FEN filtering, as entered (two-way). */
readonly filterFen: _angular_core.ModelSignal;
/** Whether the game list is sorted oldest-first (two-way). */
readonly sortAscending: _angular_core.ModelSignal;
/** Which left-panel sections are expanded, keyed by section id. */
readonly leftPanelSections: _angular_core.ModelSignal>;
/** Parsed metadata for every game; drives the game-list navigator. */
readonly gamesMetadata: _angular_core.InputSignal;
/** Metadata of the games matching the active filters. */
readonly filteredGameInfos: _angular_core.InputSignal;
/** Number of games matching the active filters. */
readonly totalFilteredCount: _angular_core.InputSignal;
/** Whether a filter request is in flight. */
readonly isFiltering: _angular_core.InputSignalWithTransform;
/** Index of the game currently loaded in the board. */
readonly currentGameIndex: _angular_core.InputSignal;
/** How many games are selected for batch operations. */
readonly selectedGamesCount: _angular_core.InputSignal;
/** Whether a previous game exists in the current navigation order. */
readonly canGoPrev: _angular_core.InputSignalWithTransform;
/** Whether a next game exists in the current navigation order. */
readonly canGoNext: _angular_core.InputSignalWithTransform;
/** White player of the loaded game, for the game-list header. */
readonly currentWhitePlayer: _angular_core.InputSignal;
/** Black player of the loaded game, for the game-list header. */
readonly currentBlackPlayer: _angular_core.InputSignal;
/** Result of the loaded game, for the game-list header. */
readonly currentGameResult: _angular_core.InputSignal;
/** The user asked to apply the current filter selection. */
readonly applyFilter: _angular_core.OutputEmitterRef;
/** The user asked to reset all filters. */
readonly clearFilters: _angular_core.OutputEmitterRef;
/** A game was picked from the list; emits its index. */
readonly loadGame: _angular_core.OutputEmitterRef;
/** A game's selection checkbox was toggled; emits its index. */
readonly toggleGameSelection: _angular_core.OutputEmitterRef;
/** Navigate to the previous game in the filtered order. */
readonly prevGame: _angular_core.OutputEmitterRef;
/** Navigate to the next game in the filtered order. */
readonly nextGame: _angular_core.OutputEmitterRef;
/** Reverse the game-list sort direction. */
readonly toggleSortDirection: _angular_core.OutputEmitterRef;
/** A collapsible section was toggled; emits the section id. */
readonly toggleLeftSection: _angular_core.OutputEmitterRef;
/** Show every filtered game instead of the limited page. */
readonly showAllFilteredGames: _angular_core.OutputEmitterRef;
/** Return to the limited game page. */
readonly showLimitedGames: _angular_core.OutputEmitterRef;
/** Capture the board's current position as the FEN filter value. */
readonly snapshotCurrentPosition: _angular_core.OutputEmitterRef;
/** Resolves an ECO code to its opening move sequence, supplied by the container. */
readonly getOpeningMoves: _angular_core.InputSignal<((code: string) => string) | undefined>;
/** Safe wrapper for invoking getOpeningMoves in templates. */
getOpeningMovesSafe(code: string): string;
/** Selected Lichess archive year (two-way). */
readonly lichessYear: _angular_core.ModelSignal;
/** Selected Lichess archive month, 1-12 (two-way). */
readonly lichessMonth: _angular_core.ModelSignal;
/** Supplies the selectable years; provided by the container. */
readonly getLichessYears: _angular_core.InputSignal<(() => number[]) | undefined>;
/** Supplies the selectable months; provided by the container. */
readonly getLichessMonths: _angular_core.InputSignal<(() => number[]) | undefined>;
/** Expands or collapses one left-panel section. */
toggleSection(section: string): void;
/** Applies the ECO code chosen in the dropdown. */
updateFilterEco(event: Event): void;
/** Adds or removes one time-control key from the selection. */
toggleTimeControl(value: string, event: Event): void;
/** Selects every time control present in the loaded collection. */
selectAllTimeControls(): void;
/** Clears the time-control selection. */
clearTimeControls(): void;
/** Applies the event chosen in the dropdown. */
updateFilterEvent(event: Event): void;
/** Applies the broadcast chosen in the dropdown. */
updateFilterBroadcastName(event: Event): void;
/**
* Applies a rating-range preset.
*
* Accepts either an explicit `min-max` value or a single lower bound
* (`'3000'` opens the range to `4000`, anything else up to `3000`).
*/
applyRatingPreset(event: Event): void;
/** Toggles inclusion of upsets won by the lower-rated player. */
toggleUpsetWin(event: Event): void;
/** Toggles inclusion of upsets drawn by the lower-rated player. */
toggleUpsetDraw(event: Event): void;
/** Applies the minimum Elo gap for the upset filter. */
updateUpsetMinDiff(value: string): void;
/** Adds or removes one result from the result filter. */
toggleResult(value: string, event: Event): void;
/** Applies the FEN typed into the position filter. */
updateFilterFen(value: string): void;
/** Applies the lower bound of the White rating range. */
updateWhiteRating(value: string): void;
/** Applies the upper bound of the White rating range. */
updateWhiteRatingMax(value: string): void;
/** Applies the lower bound of the Black rating range. */
updateBlackRating(value: string): void;
/** Applies the upper bound of the Black rating range. */
updateBlackRatingMax(value: string): void;
/** Requests loading of the game at `index`. */
onGameClick(index: number): void;
/** Requests navigation to the previous game. */
onPrevGame(): void;
/** Requests navigation to the next game. */
onNextGame(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/** Inline styles applied to the dropdown when anchored to the viewer container. */
interface DropdownPosition {
/** Always `fixed`: the dropdown is anchored to the viewer, not the panel. */
position: 'fixed';
/** Viewport x-offset, as a CSS length. */
left: string;
/** Viewport y-offset, as a CSS length. */
top: string;
/** Dropdown width, matched to the input element. */
width: string;
/** Max height before the list scrolls internally. */
maxHeight: string;
/** Set to `hidden` while measuring, so the pre-position paint is skipped. */
visibility?: 'hidden';
}
/**
* Reusable typeahead input for filtering by player name.
*
* Provides an autocomplete dropdown with keyboard navigation,
* text highlighting of matched portions, and support for
* closing via blur (with configurable delay) or Escape.
*
* @example
* ```html
*
* ```
*/
declare class PlayerTypeaheadComponent implements AfterViewInit, OnDestroy {
/** Placeholder text for the input field. */
readonly label: _angular_core.InputSignal;
/** Full list of player name suggestions. */
readonly suggestions: _angular_core.InputSignal;
/** Two-way bound current filter value. */
readonly value: _angular_core.ModelSignal;
/** Emitted when a suggestion is selected from the dropdown. */
readonly optionSelected: _angular_core.OutputEmitterRef;
/** Whether the dropdown is open. */
readonly isOpen: _angular_core.WritableSignal;
/** Currently highlighted index in the dropdown. */
readonly activeIndex: _angular_core.WritableSignal;
/** Close timeout handle for delayed blur. */
private closeTimeout;
/** The text input element. */
readonly inputEl: _angular_core.Signal | undefined>;
/** The suggestion list element. */
readonly dropdownEl: _angular_core.Signal | undefined>;
/** Inline styles anchoring the dropdown; null keeps the CSS fallback. */
readonly dropdownPosition: _angular_core.WritableSignal;
/** Whether the dropdown opens above the input. */
readonly openUp: _angular_core.WritableSignal;
/**
* The viewer container that anchors the fixed-position dropdown.
* It establishes the containing block via layout containment
* (`container-type: inline-size`), letting the dropdown escape the
* left panel's scroll/clip context entirely.
*/
private containerEl;
/** Watches the viewer container so the dropdown follows panel resizes. */
private resizeObserver;
/** Detaches the capture-phase scroll listener added in `ngAfterViewInit`. */
private scrollCleanup;
/** Coalesces reposition work into one animation frame. */
private rafId;
/** Filtered suggestions based on current input value. */
readonly filteredSuggestions: _angular_core.Signal;
/**
* Resets the highlighted suggestion whenever the dropdown (re)opens, so a
* stale index from a previous query can never point past the new list.
*/
constructor();
/**
* Handles input events, updating the value and keeping the dropdown open.
*/
onInput(event: Event): void;
/** Opens the dropdown and resets selection index. */
open(): void;
/**
* Closes the dropdown after a delay to allow mousedown on items to fire first.
*/
close(): void;
/** Selects a player suggestion, updates the value, and closes the dropdown. */
select(player: string): void;
/**
* Handles keyboard navigation in the dropdown.
* Arrow keys navigate, Enter selects, Escape closes.
*/
onKeydown(event: KeyboardEvent): void;
/**
* Splits text into match/non-match segments for highlighting.
* Delegates to the standalone {@link highlightMatch} utility.
*/
highlightText(text: string, query: string): TextSegment[];
/** Cancels any pending close timeout. */
private cancelClose;
/**
* Finds the viewer container to anchor the dropdown against and starts
* observing the layout, so the fixed-position dropdown tracks the input
* while ancestor scroll or panel-resize changes the input's position.
*/
ngAfterViewInit(): void;
/** Detaches the scroll and resize listeners set up in `ngAfterViewInit`. */
ngOnDestroy(): void;
/**
* Clears the anchored dropdown styles, restoring the CSS fallback
* (only relevant when the dropdown is closed).
*/
private resetPosition;
/** Coalesces repositioning work into a single animation frame. */
private schedulePosition;
/**
* Anchors the dropdown to the input using fixed positioning relative to the
* viewer container, so it escapes the left panel's scroll/clip context.
* Opens upward when there is not enough room below the input.
*/
private positionDropdown;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* Lichess broadcast archive URL helpers.
*
* Extracted from the viewer component so the derivation rule is unit-testable
* on its own — it is the one piece of non-obvious behaviour behind the URL
* field (generated URLs follow the picker, hand-entered ones do not).
*/
/**
* Path of the Lichess monthly broadcast archive for a year/month pair.
*
* @param year — Four-digit year.
* @param month — Month number (1-12); zero-padded to two digits.
*/
declare function lichessBroadcastUrl(year: number, month: number): string;
/**
* Whether `url` is a URL this library generated from the year/month picker,
* as opposed to one the user typed or restored from a previous session.
*/
declare function isLichessBroadcastUrl(url: string): boolean;
/**
* Resolves the PGN source URL shown in the load panel.
*
* The URL follows the Lichess year/month picker, but a value the user chose —
* a hand-entered URL, or one restored from storage that is unrelated to the
* picker — is preserved across later picker changes.
*
* @param next — The year/month the picker currently shows.
* @param previousUrl — The URL currently in the field, if any.
* @returns The URL the field should show.
*/
declare function resolveBroadcastUrl(next: {
year: number;
month: number;
}, previousUrl: string | undefined): string;
/**
* Load & Cache panel for the PGN viewer — right sidebar bottom section.
*
* Provides:
* - PGN text input textarea with clipboard buttons
* - FEN indexing options (start positions, max plies)
* - Cache management (clear, info)
* - File-based loading (ZIP, PGN file picker)
* - Lichess database date picker (year/month)
* - URL-based loading with support for .zst compressed files
* - Loading progress bar with status message
*
* @example
* ```html
*
* ```
*/
declare class LoadCachePanelComponent {
/** Whether a load is in progress. */
readonly isLoading: _angular_core.InputSignalWithTransform;
/** Load progress, 0-100. */
readonly loadingProgress: _angular_core.InputSignal;
/** Human-readable description of the current load step. */
readonly loadingStatus: _angular_core.InputSignal;
/** Cached-entry count and estimated size, or `null` while unknown. */
readonly cacheInfo: _angular_core.InputSignal<{
count: number;
estimatedBytes: number;
} | null>;
/** PGN text typed or pasted into the panel (two-way). */
readonly pgnInput: _angular_core.ModelSignal;
/** PGN source URL typed into the panel (two-way). */
readonly urlInput: _angular_core.ModelSignal;
/** Whether to build a starting-position FEN index (two-way). */
readonly indexStartPositions: _angular_core.ModelSignal;
/** Max half-moves replayed per game when indexing (two-way). */
readonly maxFenPlies: _angular_core.ModelSignal;
/** Selected Lichess archive year (two-way). */
readonly lichessYear: _angular_core.ModelSignal;
/** Selected Lichess archive month, 1-12 (two-way). */
readonly lichessMonth: _angular_core.ModelSignal;
/** PGN text is ready to be parsed; emits the text. */
readonly loadPgnString: _angular_core.OutputEmitterRef;
/** The user asked to clear the PGN cache. */
readonly clearPgnCache: _angular_core.OutputEmitterRef;
/** The user asked to refresh the cache statistics. */
readonly refreshCacheInfo: _angular_core.OutputEmitterRef;
/** The user asked to load the selected Lichess month. */
readonly loadFromLichess: _angular_core.OutputEmitterRef;
/** The user asked to load the URL in the input. */
readonly loadFromUrl: _angular_core.OutputEmitterRef;
/** The user asked to load PGN text from the clipboard. */
readonly loadFromClipboardEvent: _angular_core.OutputEmitterRef;
/** The user asked to copy the PGN text to the clipboard. */
readonly copyToClipboardEvent: _angular_core.OutputEmitterRef;
/**
* A local file could not be read or contained no PGN entry.
*
* The panel is presentational and has no access to user-facing
* notification, so the container turns this into a message.
*/
readonly fileLoadFailed: _angular_core.OutputEmitterRef;
/**
* Selectable archive years, oldest first.
*
* The lower bound matches the earliest Lichess monthly broadcast archive;
* the upper bound is the current year.
*/
get years(): number[];
/**
* Selectable months for the selected year.
*
* A past year offers all twelve; the current year offers only the months
* that have already ended, because a broadcast archive is published after
* the month closes.
*/
get months(): number[];
/** Applies the selected year and clamps the month to an available one. */
onLichessYearChange(event: Event): void;
/** Applies the selected month. */
onLichessMonthChange(event: Event): void;
/** Applies the edited PGN text. */
onPgnInputChange(event: Event): void;
/** Applies the edited source URL. */
onUrlInputChange(event: Event): void;
/** Applies the starting-position indexing checkbox. */
onIndexStartPositionsChange(event: Event): void;
/** Applies the indexing replay window, ignoring values below 1. */
onMaxFenPliesChange(event: Event): void;
/** Extracts the first `.pgn` entry from a chosen zip archive and emits it. */
onPgnZipSelected(event: Event): Promise;
/** Emits the text of a chosen `.pgn` file. */
onPgnFileSelected(event: Event): void;
/** Reads a file as UTF-8 text and emits it, or reports the failure. */
private handleFileRead;
/** Whether the load & cache panel is expanded (two-way). */
readonly expanded: _angular_core.ModelSignal;
/** Expands or collapses the load & cache panel. */
toggleExpanded(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* Displays the move list for the current game as clickable buttons.
*
* Each move is rendered in chess notation with move numbers (1., 2., etc.).
* Active and last-move buttons are highlighted. Move clocks are shown
* alongside moves when available. The list auto-scrolls to keep the
* active move visible when the current move index changes.
*
* @example
* ```html
*
* ```
*/
declare class MoveListComponent {
/** SAN move strings for the current game. */
readonly moves: _angular_core.InputSignal;
/** Per-move clock strings (empty string if no clock data). */
readonly moveClocks: _angular_core.InputSignal;
/** Current zero-based move index (-1 = start position). */
readonly currentMoveIndex: _angular_core.InputSignal;
/** Whether to highlight the last move in the game. */
readonly highlightLastMove: _angular_core.InputSignalWithTransform;
/** Whether the moves section is expanded/collapsed. */
readonly expanded: _angular_core.ModelSignal;
/** Emitted when the user clicks a move to jump to it. */
readonly jumpToMove: _angular_core.OutputEmitterRef;
/** View query for the move list container (for auto-scroll). */
readonly moveListRef: _angular_core.Signal | undefined>;
/**
* Keeps the active move visible: scrolls it into the nearest edge of the
* list whenever the current move index changes.
*/
constructor();
/** Expands or collapses the move-list panel (two-way bound). */
toggleExpanded(): void;
/** Returns the move number for a given half-move index (0-indexed). */
moveNumber(index: number): number;
/** Whether a given index starts a new move pair (white's move). */
isWhiteMove(index: number): boolean;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵcmp: _angular_core.ɵɵComponentDeclaration;
}
/**
* Criteria for filtering a parsed game collection in the PGN processor worker.
*
* All string fields are matched case-insensitively as substrings.
* Rating fields default to 0 (no lower bound) or Infinity (no upper bound) when unset.
*
* @example
* ```typescript
* const criteria: FilterCriteria = {
* white: 'carlsen',
* black: '',
* result: '1-0',
* moves: true,
* ignoreColor: false,
* targetMoves: ['e4', 'e5', 'Nf3'],
* minWhiteRating: 2500,
* minBlackRating: 2400,
* maxWhiteRating: Infinity,
* maxBlackRating: Infinity,
* eco: 'B33',
* timeControl: ['180+2', '300+0'],
* event: '',
* filterByFen: false,
* targetFen: '',
* sortAscending: false,
* };
* ```
*/
interface FilterCriteria {
/** Filter by white player name (case-insensitive substring match). */
white: string;
/** Filter by black player name (case-insensitive substring match). */
black: string;
/** Comma-separated result strings: `"1-0"`, `"0-1"`, `"draw"`, or `"*"` for unfinished. */
result: string;
/** When `true`, filter games by the {@link targetMoves} opening sequence. */
moves: boolean;
/** When `true`, treat {@link white} and {@link black} fields as matching either color. */
ignoreColor: boolean;
/** SAN move sequence the game must be prefixed with (only used when {@link moves} is `true`). */
targetMoves: string[];
/** When `true`, filter games by the {@link targetFen} position.
* Games that reach the target board position at any point are included. */
filterByFen: boolean;
/** Target FEN string (piece placement + active color + castling +
* en passant) for position-based filtering. Only used when
* {@link filterByFen} is `true`. */
targetFen: string;
/** Minimum white Elo rating (inclusive). Default 0. */
minWhiteRating: number;
/** Minimum black Elo rating (inclusive). Default 0. */
minBlackRating: number;
/** Maximum white Elo rating (inclusive). Use `Infinity` for no upper bound. */
maxWhiteRating: number;
/** Maximum black Elo rating (inclusive). Use `Infinity` for no upper bound. */
maxBlackRating: number;
/** ECO code filter (case-insensitive substring, e.g. `"B33"`). */
eco: string;
/**
* Time control filter — normalized time controls to keep
* (e.g. `["180+2", "60+0"]`). A game matches when its normalized
* time control equals any entry. Empty array means no filter.
*/
timeControl: string[];
/** Event/tournament name filter (case-insensitive substring). */
event: string;
/** Broadcast name filter (case-insensitive substring). */
broadcastName: string;
/**
* Sort direction for filtered results.
* `false` = descending (highest Elo first, default).
* `true` = ascending (lowest Elo first).
*/
sortAscending: boolean;
/**
* When `true`, keep only upset games: the weaker-rated player
* (by Elo) either beats or draws the stronger-rated player.
* Requires both players to have a known Elo and the rating gap to
* be at least {@link minUpsetEloDiff}. When enabled, results are
* sorted by upset size (rating gap) instead of Elo sum.
*/
upsetEnabled: boolean;
/** When `true` and {@link upsetEnabled}, include upsets where the weaker player wins. */
upsetWin: boolean;
/** When `true` and {@link upsetEnabled}, include upsets where the weaker player draws. */
upsetDraw: boolean;
/** Minimum Elo gap between the players for a game to count as an upset. Default 0. */
minUpsetEloDiff: number;
}
/**
* Discriminated union of responses sent from the PGN processor worker to the main thread.
*
* The `id` field matches the correlation ID from the originating {@link WorkerMessage}.
*/
type WorkerResponse =
/** Response to a `'load'` message with game count and metadata. */
{
type: 'load';
payload: {
count: number;
metadata: GameMetadata[];
};
id: number;
}
/** Response to a `'filter'` message with matching game indices. */
| {
type: 'filter';
payload: number[];
id: number;
}
/** Response to a `'loadGame'` message with moves, cleaned PGN, evaluations, and optional error. */
| {
type: 'loadGame';
payload: {
moves: string[];
pgn: string;
evaluations: (string | null)[];
error?: string;
};
id: number;
}
/** Progress update during long-running operations (load, filter). */
| {
type: 'progress';
payload: {
percent: number;
status: string;
};
id: number;
}
/**
* Response to `'loadFromCache'` when no usable IndexedDB entry exists. The
* main thread should fall back to downloading and parsing the source.
*/
| {
type: 'cacheMiss';
payload?: undefined;
id: number;
}
/** Error response for any message type. */
| {
type: 'error';
payload: string;
id: number;
};
/**
* Metadata extracted from a single PGN game header.
*
* Used for displaying game lists, filtering, and sorting without parsing full move data.
* The `timeControlNormalized` field converts human-readable time controls
* (e.g. `"90+30"`, `"3:0"`) into a uniform `"baseSeconds+incrementSeconds"` format.
*/
interface GameMetadata {
/** 1-based game number within the loaded PGN collection. */
number: number;
/** White player display name (includes title and Elo if present, e.g. `"GM Carlsen (2850)"`). */
white: string;
/** Black player display name (includes title and Elo if present). */
black: string;
/** Normalized result: `"1-0"`, `"0-1"`, `"½-½"`, or `"*"`. */
result: string;
/** White player Elo rating (0 if missing). */
whiteElo: number;
/** Black player Elo rating (0 if missing). */
blackElo: number;
/** ECO (Encyclopedia of Chess Openings) code (e.g. `"B33"`). */
eco?: string;
/** Raw time control string from the PGN header. */
timeControl?: string;
/** Normalized time control in `"seconds+increment"` format, or `undefined` if unparseable. */
timeControlNormalized?: string;
/** Event/tournament name from the PGN header. */
event?: string;
/** Broadcast name from the PGN header (e.g. Lichess broadcast name). */
broadcastName?: string;
}
/**
* Serialized form of the worker's cached state for IndexedDB persistence.
*
* The FEN cache is stored as `[gameIndex, normalizedFen[]][]` (serialized
* from `Map>`) so it survives structured clone.
*/
interface CachedPgnData {
/** Raw PGN text for each game, split by `[Event ...]` header. */
games: string[];
/** Parsed metadata for each game (headers only, no move data). */
gameMetadata: GameMetadata[];
/**
* Serialized FEN position cache.
* Each entry: `[gameIndex, normalizedFenString[]]`.
* The FEN strings are normalized (4-field: piece placement, active color,
* castling, en passant) and deduplicated per game.
*/
fenCache: [number, string[]][];
/** When this cache entry was created (epoch ms). */
createdAt: number;
/**
* Whether the FEN index was actually built for this entry. `false`/absent
* means {@link fenCache} holds empty sets (indexing was disabled), so
* position filters cannot be served from this entry.
*/
indexed?: boolean;
/** Max half-moves replayed per game when the FEN index was built. */
maxFenPlies?: number;
}
/**
* Maps a PGN source (URL) to the content hash under which its parsed games and
* FEN index are stored in IndexedDB.
*
* The content hash alone cannot be computed without first downloading and
* decompressing the archive, so this bookmark lets the application detect a
* usable cache entry at startup and skip the download entirely.
*/
interface PgnSourceCacheEntry {
/** SHA-256 hash of the decompressed PGN content. */
pgnHash: string;
/** Whether the cached entry contains a built FEN index. */
indexed: boolean;
/** Max half-moves replayed per game for the cached FEN index. */
maxFenPlies: number;
/** When this mapping was recorded (epoch ms). */
createdAt: number;
}
/**
* Service for caching parsed PGN data (games, metadata, FEN positions) in
* IndexedDB. Allows re-opening a previously loaded PGN without re-parsing
* the entire file.
*
* Uses raw IndexedDB (no external dependency). Provided at root level so a
* single database connection is shared across the application.
*/
declare class PgnCacheService {
/** Durable store used for the URL → content-hash bookmark map. */
private readonly store;
/** Cached open handle, so the database is opened at most once. */
private dbPromise;
/**
* Opens (or creates) the IndexedDB database and returns a handle.
*/
private getDb;
/**
* Computes a SHA-256 hex digest of the given string using the
* SubtleCrypto API.
*/
hashPgn(pgn: string): Promise;
/**
* Retrieves cached PGN data by hash, or `null` if not found or expired.
*
* @param pgnHash — SHA-256 hash of the original PGN string.
* @param ttlMs — Time-to-live in milliseconds (default 7 days).
*/
getCached(pgnHash: string, ttlMs?: number): Promise;
/**
* Stores parsed PGN data in the cache, keyed by the PGN content hash.
*
* Automatically evicts the oldest entries when the cache exceeds
* {@link MAX_ENTRIES}.
*/
setCache(pgnHash: string, data: CachedPgnData): Promise;
/**
* Deletes a single cache entry by hash.
*/
private deleteEntry;
/**
* Evicts the oldest entries when the store exceeds {@link MAX_ENTRIES}.
*/
private evictIfNeeded;
/**
* Removes all cached PGN data from IndexedDB.
*/
clearCache(): Promise;
/**
* Returns the number of cached entries and their total estimated size.
*
* On desktop the parsed archives live on disk behind the local server, so
* the figures come from `/api/cache-info` instead of IndexedDB.
*/
getCacheInfo(): Promise<{
count: number;
estimatedBytes: number;
}>;
/**
* Looks up the cached content hash for a PGN source without touching the
* content. Used to detect a cache hit before downloading the archive.
*
* @param source — Source identifier (typically the PGN URL).
* @returns The bookmark entry, or `null` when the source is not remembered.
*/
getSourceEntry(source: string): PgnSourceCacheEntry | null;
/**
* Remembers which content hash backs a PGN source, so a later session can
* restore it from the cache without downloading and decompressing it again.
*/
setSourceEntry(source: string, entry: PgnSourceCacheEntry): void;
/** Removes all source bookmarks (used when the PGN cache is cleared). */
clearSourceEntries(): void;
/**
* Fills the desktop snapshot with the source bookmarks from disk.
*
* A no-op in the browser. Hosts should await this before reading
* {@link getSourceEntry} at startup on desktop.
*/
hydrateSourceEntries(): Promise;
/** Reads the URL → hash map, tolerating absent or corrupt payloads. */
private readSourceMap;
/** Keeps only the {@link MAX_SOURCE_ENTRIES} most recently recorded sources. */
private pruneSourceMap;
static ɵfac: _angular_core.ɵɵFactoryDeclaration;
static ɵprov: _angular_core.ɵɵInjectableDeclaration;
}
/**
* Container for the full-featured PGN viewer application.
*
* Owns all state signals and business logic, delegating rendering to
* focused presentational sub-components:
* - {@link GameFilterPanelComponent} — left sidebar filters
* - {@link BoardDisplayComponent} — center board area
* - {@link MoveListComponent} — right panel move list
* - {@link ReplayPanelComponent} — right panel replay controls
* - {@link LoadCachePanelComponent} — right panel load & cache
*
* @example
* ```html
*
* ```
*/
declare class NgxPgnViewerComponent implements OnDestroy {
/** Owns the PGN worker and the Stockfish worker. */
private readonly pgnViewerEngine;
/** Sink for user-facing messages; defaults to the console. */
private readonly notifier;
/** Parsed-game cache and URL → hash bookmarks. */
private readonly pgnCacheService;
/** Opens the pawn-promotion dialog during interactive play. */
private readonly promotionService;
/** Persists and restores the filter selection and data source. */
private readonly pgnViewerSettings;
/** PGN text to load. Changing it (non-empty) starts a load. */
pgn: _angular_core.InputSignal;
/** Whether to highlight the origin and destination of the last move. */
highlightLastMove: _angular_core.InputSignalWithTransform;
/** Board orientation; `true` puts Black at the bottom (two-way). */
flipped: _angular_core.ModelSignal;
/** Whether to render 3D Staunton pieces (two-way). */
in3d: _angular_core.ModelSignal;
/** Width of the left filter panel in pixels (two-way). */
leftPanelWidth: _angular_core.ModelSignal;
/** Width of the right panel in pixels (two-way). */
rightPanelWidth: _angular_core.ModelSignal;
/** Whether the move-list panel is expanded (two-way). */
movesExpanded: _angular_core.ModelSignal;
/**
* Emitted once when durable state has been restored.
*
* Hosts that need to read `urlInput`/`restoredStateFromStorage` at startup
* can `await whenStateReady()` instead; this output exists for hosts that
* prefer the reactive form.
*/
readonly stateRestored: _angular_core.OutputEmitterRef;
/**
* Emitted when a load starts, carrying the initial status text.
*
* Load progress afterwards is reported through `loadProgress`.
*/
readonly loadStarted: _angular_core.OutputEmitterRef<{
status: string;
}>;
/** Emitted whenever load progress advances. */
readonly loadProgress: _angular_core.OutputEmitterRef<{
percent: number;
status: string;
}>;
/**
* Emitted for every load failure, in addition to the user-facing notice.
*
* This is the single place a host needs to handle to surface load errors
* programmatically (telemetry, retry UI, a custom banner).
*/
readonly loadFailed: _angular_core.OutputEmitterRef;
/** Parsed metadata for every game in the loaded collection. */
gamesMetadata: _angular_core.WritableSignal;
/** Index of the game currently loaded into the board. */
currentGameIndex: _angular_core.WritableSignal;
/** SAN moves of the loaded game. */
moves: _angular_core.WritableSignal;
/** Zero-based index of the displayed move; `-1` is the start position. */
currentMoveIndex: _angular_core.WritableSignal;
/** FEN of the position currently displayed on the board. */
currentFen: _angular_core.WritableSignal;
/** Whether a load or parse is in progress. */
isLoading: _angular_core.WritableSignal;
/** Load progress, 0-100. */
loadingProgress: _angular_core.WritableSignal;
/** Human-readable description of the current load step. */
loadingStatus: _angular_core.WritableSignal;
/** Content hash of the PGN being loaded, used for cache bookkeeping. */
lastPgnHash: string | null;
/** Indices of the games selected for batch operations. */
selectedGames: _angular_core.WritableSignal>;
/** White-player name filter. */
filterWhite: _angular_core.WritableSignal;
/** Black-player name filter. */
filterBlack: _angular_core.WritableSignal;
/** Selected results; empty means no result filter. */
filterResult: _angular_core.WritableSignal;
/** Whether the opening-move prefix filter is active. */
filterMoves: _angular_core.WritableSignal;
/** Whether player names match either colour. */
ignoreColor: _angular_core.WritableSignal;
/** Whether upset filtering is enabled. */
filterUpsetEnabled: _angular_core.WritableSignal;
/** Include upsets won by the lower-rated player. */
filterUpsetWin: _angular_core.WritableSignal;
/** Include upsets drawn by the lower-rated player. */
filterUpsetDraw: _angular_core.WritableSignal;
/** Minimum Elo gap between players for a game to count as an upset. */
filterUpsetMinDiff: _angular_core.WritableSignal;
/** Whether rating-range filtering is enabled. */
filterRatingEnabled: _angular_core.WritableSignal;
/** Lower bound of the White rating range, as entered. */
filterWhiteRating: _angular_core.WritableSignal;
/** Lower bound of the Black rating range, as entered. */
filterBlackRating: _angular_core.WritableSignal;
/** Upper bound of the White rating range, as entered. */
filterWhiteRatingMax: _angular_core.WritableSignal;
/** Upper bound of the Black rating range, as entered. */
filterBlackRatingMax: _angular_core.WritableSignal;
/** Selected ECO code, or `''`. */
filterEco: _angular_core.WritableSignal;
/** Selected time-control keys; empty means no filter. */
filterTimeControl: _angular_core.WritableSignal;
/** Selected event name, or `''`. */
filterEvent: _angular_core.WritableSignal;
/** Selected broadcast name, or `''`. */
filterBroadcastName: _angular_core.WritableSignal;
/** Target position for FEN filtering. */
filterFen: _angular_core.WritableSignal;
/** Whether position (FEN) filtering is active. */
filterByFenEnabled: _angular_core.WritableSignal;
/**
* Whether to build a starting-position FEN index.
*
* Defaults to `true` in the packaged desktop app, which has the resources
* to index every game, and `false` on the web unless the user opts in.
*/
indexStartPositions: _angular_core.WritableSignal;
/** Max half-moves replayed per game when building the FEN index. */
maxFenPlies: _angular_core.WritableSignal;
/** Whether the game list is sorted oldest-first. */
sortAscending: _angular_core.WritableSignal;
/** Distinct White player names in the loaded collection. */
uniqueWhitePlayers: _angular_core.WritableSignal;
/** Distinct Black player names in the loaded collection. */
uniqueBlackPlayers: _angular_core.WritableSignal;
/** ECO code → game count, for the ECO dropdown. */
uniqueEcoCodes: _angular_core.WritableSignal