import type { LocalePack } from '../i18n/types.js'; import { EditorMode, RpEditorTheme, CropAspectRatio, ImageFilterPreset, ImageAdjustments } from '../types/index.js'; export interface ToolbarCallbacks { onModeChange: (mode: EditorMode) => void; onZoomIn: () => void; onZoomOut: () => void; onRotateLeft: () => void; onRotateRight: () => void; onUndo: () => void; onRedo: () => void; onReset: () => void; onColorChange: (color: string) => void; onBrushWidthChange: (width: number) => void; onCropRatioChange: (ratio: number | null) => void; onApplyCrop: () => void; onCancelCrop: () => void; onDeleteAnnotation?: () => void; onFlipHorizontal?: () => void; onFlipVertical?: () => void; onFitZoom?: () => void; onZoomTo?: (level: number) => void; onOpacityChange?: (opacity: number) => void; onTextSize?: (size: number) => void; onEraserSize?: (size: number) => void; onFilterPreset?: (preset: ImageFilterPreset) => void; onAdjustChange?: (key: K, value: ImageAdjustments[K]) => void; onResetEffects?: () => void; getImageEffects?: () => { preset: ImageFilterPreset; adjustments: ImageAdjustments; }; onApply?: () => void; onClose?: () => void; onToggleFullscreen?: () => void; } /** * Additional options plumbed into the Toolbar beyond raw callbacks. * Kept as a single bag so future config knobs can be added without * churning the constructor signature. */ export interface ToolbarOptions { filterPresets?: ImageFilterPreset[]; filterPresetLabels?: Partial>; /** Override the empty-state title (default `'Drop an image or click to upload'`). */ emptyStateTitle?: string; /** * Override the empty-state subtitle (default `'Supported: PNG, JPEG, HEIC'`). * Pass `''` (empty string) to hide the subtitle row entirely. */ emptyStateSubtitle?: string; /** * Optional bundled i18n pack. When supplied, every tool label, * shape name, panel heading, hint, and tooltip in the shell is * pulled from the pack instead of the hard-coded English text. * When omitted the toolbar behaves exactly as before (English). */ labels?: LocalePack; /** Current image index (1-based) for multi-image flows. */ currentImageIndex?: number; /** Total image count for multi-image flows. */ totalImages?: number; /** Currently active annotation color across tools. */ activeColor?: string; } export declare class Toolbar { private container; private theme; private colorPalette; private cropRatios; private callbacks; private disabledSet; private options; private rootEl; private stageSlotEl; private propsPanelEl; private bottomSliderEl; private zoomLabelEl; private zoomMenuEl; private fullscreenBtnEl; private fullscreenChangeHandler; private toastRootEl; private statusLiveEl; private activeMode; private quickActionFlashTimers; private zoomLevel; private canUndo; private canRedo; private recentColors; private activeColor; private customPaletteColor; private outsideClickHandler; /** Resolved i18n pack. `null` = fall back to the hard-coded English literals. */ private labels; constructor(container: HTMLElement, theme: RpEditorTheme, colorPalette: string[], cropRatios: CropAspectRatio[], callbacks: ToolbarCallbacks, disabledFeatures?: string[], options?: ToolbarOptions); render(): void; /** Slot the canvas wrapper element into the shell stage. */ attachCanvasWrapper(wrapper: HTMLElement): void; updateZoomState(zoomLevel: number): void; updateHistoryState(canUndo: boolean, canRedo: boolean): void; setActiveMode(mode: EditorMode): void; /** * Keep the palette UI in sync with the editor's single active color, * including custom colors that are not part of the static base palette. */ setActiveColor(color: string): void; showToast(message: string, kind?: 'info' | 'error'): void; destroy(): void; /** Expose the stage slot so the editor can mount its canvas into it. */ getStageSlot(): HTMLElement | null; private applyThemeVars; private buildTopBar; private buildZoomMenu; private getImageCounterText; private buildLeftRail; private buildRightRail; private buildStage; private buildPropsPanel; private updatePropsPanel; private renderDrawProps; private renderEraserProps; private renderTextProps; private renderCropProps; private renderShapeProps; private renderCalloutProps; private renderMoveProps; private renderFilterProps; private renderAdjustProps; private buildBipolarSlider; private buildColorSection; private pushRecentColor; private normalizeColorKey; private isColorInBasePalette; private toHexColor; private syncColorSectionUi; private buildSlider; private buildBottomBar; private updateBottomSlider; private flashQuickAction; private updateActiveTool; private updateHistoryButtons; private setDisabledState; private updateZoomLabel; private handleFit; private makeIconButton; private attachTooltip; /** * Swap the fullscreen button's icon and tooltip to reflect the * current `document.fullscreenElement` state. Called on click and * on `fullscreenchange` (covers Esc-to-exit). */ private refreshFullscreenButton; }