import type { SceneAnimationCancellationReason } from "@skenora/contracts"; export interface AnimationPropertyOwner { readonly keys: readonly string[]; /** Continuous controllers block replacement in either direction. */ readonly kind: "animation" | "exclusive"; /** Clips reserve one slot per participant; independent writers use one. */ readonly slots?: number; cancel(reason: SceneAnimationCancellationReason): void; } export declare const CAMERA_ANIMATION_PROPERTY_KEY: string; export declare class AnimationPropertyConflict extends Error { readonly code: "conflict" | "budget"; constructor(code: "conflict" | "budget"); } /** One session's writer arbitration and notification boundary; no scene values. */ export declare class AnimationPropertyOwners { #private; readonly maxRunning: number; constructor(maxRunning?: number); transaction(commit: () => T): T; notify(callback: () => void): void; preflight(owner: AnimationPropertyOwner): void; acquire(owner: AnimationPropertyOwner): void; /** Call only after preparing every field/instance without writes. */ write(keys: readonly string[], commit: () => void, reason?: SceneAnimationCancellationReason): void; release(owner: AnimationPropertyOwner): void; has(keys: readonly string[]): boolean; /** Lifecycle invalidation may also revoke exclusive continuous controllers. */ cancel(keys: readonly string[], reason: SceneAnimationCancellationReason): void; cancelAll(reason: SceneAnimationCancellationReason): void; } /** Tuple encoding avoids collisions with authored IDs containing separators. */ export declare function animationPropertyKey(kind: "entity" | "material", id: string, property: string): string; //# sourceMappingURL=animation-property-owners.d.ts.map