import type { PPTElement, PPTLineElement, Slide } from '../types/slides'; interface RotatedElementData { left: number; top: number; width: number; height: number; rotate: number; } interface Point { x: number; y: number; } interface IdMap { [id: string]: string; } /** * Bounding box of an element's rect after rotation on the canvas. * @param element Position, size, and rotation of the element */ export declare const getRectRotatedRange: (element: RotatedElementData) => { xRange: number[]; yRange: number[]; }; /** * Offset between an element's axis-aligned bounds before and after rotation. * @param element Position, size, and rotation of the element */ export declare const getRectRotatedOffset: (element: RotatedElementData) => { offsetX: number; offsetY: number; }; /** * Local control points that define a line's painted path. * Includes elbows so a bent/curved stroke is never clipped to the start–end chord. */ export declare const getLineLocalPoints: (element: PPTLineElement) => [number, number][]; /** * Axis-aligned bounds of a single element on the canvas. * @param element Element data */ export declare const getElementRange: (element: PPTElement) => { minX: any; maxX: any; minY: any; maxY: any; }; export type ElementRangeAlign = { minX?: number; maxX?: number; centerX?: number; minY?: number; maxY?: number; centerY?: number; }; /** * Shift left/top so the element's painted AABB matches the given edges or centers. * Lines use control-point bounds, not the start–end chord. */ export declare const alignElementToRange: (element: PPTElement, target: ElementRangeAlign) => void; /** * Combined axis-aligned bounds of multiple elements on the canvas. * @param elementList Elements to measure */ export declare const getElementListRange: (elementList: PPTElement[]) => { minX: number; maxX: number; minY: number; maxY: number; }; /** * Whether the selection is the full membership of a single group. * @param elements Selected elements */ export declare const isSingleGroupSelection: (elements: PPTElement[]) => boolean; /** * Whether the group can be rotated as a unit. * @param elements Group members */ export declare const canRotateGroupElements: (elements: PPTElement[]) => boolean; /** * Center of the combined bounds of a set of elements. * @param elements Elements in the group * @param rotate Reference rotation: bounds are aligned to this angle before computing the center */ export declare const getGroupElementCenter: (elements: PPTElement[], rotate?: number) => Point; /** * Normalize an angle to the [-180, 180] range. * @param angle Angle in degrees */ export declare const normalizeAngle: (angle: number) => number; /** * Rotate a point around a center by the given angle. * @param point Point to rotate * @param center Rotation center * @param angle Rotation in degrees */ export declare const rotatePoint: (point: Point, center: Point, angle: number) => Point; /** * Rotate a rect-like element by rotating its center and adding to `rotate`. * @param element Element to rotate * @param center Group rotation center * @param angle Rotation in degrees */ export declare const rotateRectLikeElement: (element: Exclude, center: Point, angle: number) => { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'audio'; fixedRatio: boolean; color: string; loop: boolean; autoplay: boolean; src: string; poster?: string; ext?: string; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'chart'; fill?: string; chartType: import("../types/slides").ChartType; data: import("../types/slides").ChartData; options?: import("../types/slides").ChartOptions; outline?: import("../types/slides").PPTElementOutline; themeColors: string[]; textColor?: string; lineColor?: string; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'code'; code: string; language: string; theme: string; fontSize: number; showLineNumbers: boolean; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'image'; fixedRatio: boolean; src: string; outline?: import("../types/slides").PPTElementOutline; filters?: import("../types/slides").ImageElementFilters; clip?: import("../types/slides").ImageElementClip; flipH?: boolean; flipV?: boolean; shadow?: import("../types/slides").PPTElementShadow; radius?: number; colorMask?: string; imageType?: import("../types/slides").ImageType; qrCode?: { text: string; errorCorrection: 'L' | 'M' | 'Q' | 'H'; foreground: string; background: string; }; photoFrame?: { layout: string; cell: number; gutter: number; empty: boolean; sourceWidth?: number; sourceHeight?: number; }; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'latex'; latex: string; path: string; color: string; strokeWidth: number; viewBox: [number, number]; fixedRatio: boolean; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'mermaid'; code: string; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; frame?: { clipContent: boolean; }; type: 'shape'; viewBox: [number, number]; path: string; fixedRatio: boolean; fill: string; gradient?: import("../types/slides").Gradient; pattern?: string; outline?: import("../types/slides").PPTElementOutline; opacity?: number; flipH?: boolean; flipV?: boolean; shadow?: import("../types/slides").PPTElementShadow; special?: boolean; text?: import("../types/slides").ShapeText; pathFormula?: import("../types/slides").ShapePathFormulasKeys; keypoints?: number[]; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'table'; outline: import("../types/slides").PPTElementOutline; theme?: import("../types/slides").TableTheme; colWidths: number[]; cellMinHeight: number; data: import("../types/slides").TableCell[][]; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'text'; content: string; defaultFontName: string; defaultColor: string; placeholder?: string; placeholderFontSize?: number; placeholderColor?: string; placeholderAlign?: import("../types/slides").TextAlign; placeholderBold?: boolean; placeholderItalic?: boolean; placeholderLayoutHeight?: number; outline?: import("../types/slides").PPTElementOutline; fill?: string; lineHeight?: number; wordSpace?: number; opacity?: number; shadow?: import("../types/slides").PPTElementShadow; paragraphSpace?: number; vertical?: boolean; textType?: import("../types/slides").TextType; inset?: import("../types/slides").TextInset; fixedHeight?: boolean; vAlign?: import("../types/slides").TextAlignVertical; structuredText?: import("../types/slides").StructuredTextBody; left: number; top: number; rotate: number; } | { parentFrameId?: string; id: string; lock?: boolean; groupId?: string; width: number; height: number; link?: import("../types/slides").PPTElementLink; name?: string; source?: import("../types/slides").ElementSource; effects?: import("../types/slides").PPTElementEffects; type: 'video'; src: string; autoplay: boolean; poster?: string; ext?: string; left: number; top: number; rotate: number; }; /** * Rotate a line element by rotating all control points and rebuilding line data. * @param element Line element * @param center Group rotation center * @param angle Rotation in degrees */ export declare const rotateLineElement: (element: PPTLineElement, center: Point, angle: number) => PPTLineElement; export declare const getLineElementLength: (element: PPTLineElement) => number; export declare const getBroken2LineDirection: (element: PPTLineElement) => import("../types/slides").Broken2LineDirection; export interface AlignLine { value: number; range: [number, number]; } /** * Deduplicate alignment snap lines at the same position; merge their ranges to min/max. * @param lines Alignment snap lines */ export declare const uniqAlignLines: (lines: AlignLine[]) => AlignLine[]; /** * Map each slide id to a new id (used when duplicating slides to preserve references). * @param slides Slide list */ export declare const createSlideIdMap: (slides: Slide[]) => IdMap; /** * Map each element (and group) id to a new id when copying elements. * e.g. two grouped elements keep the same new groupId after copy. * @param elements Element list */ export declare const createElementIdMap: (elements: PPTElement[]) => { groupIdMap: IdMap; elIdMap: IdMap; }; /** * Header is the opaque theme color (ink by default). Body stripes are a fixed * zinc paper pair so a blue accent can never wash the grid. */ export declare const getTableThemeColors: (themeColor: string) => { header: string; stripe: string; stripeAlt: string; }; /** * SVG path `d` attribute for a line element (logical geometry). * @param element Line element */ export declare const getLineElementPath: (element: PPTLineElement) => string; /** * SVG path for rendering a line: markers stay at original start/end; stroke is inset at caps. * @param element Line element */ export declare const getLineElementRenderPath: (element: PPTLineElement) => string; /** * Whether an element is fully visible within a scroll parent's viewport (vertical). * @param element DOM element * @param parent Scroll container */ export declare const isElementInViewport: (element: HTMLElement, parent: HTMLElement) => boolean; export {};