types.tstypescript
/**
 * @category Types
 * Function signature for requesting device orientation permissions.
 *
 * Typically provided by browser vendor implementations (such as iOS Safari's
 * `DeviceOrientationEvent.requestPermission`).
 *
 * @returns A promise that resolves to `"granted"` or `"denied"`.
 */
export type RequestPermissionFn = () => Promise<"granted" | "denied">;

/**
 * @category Types
 * Represents a single calibrated orientation and rotation update dispatched by the library.
 *
 * @example
 * ```typescript
 * deviceRotation.onUpdate((update: RotationUpdate) => {
 *   const { x, y, z, w } = update.quaternion;
 *   console.log(`Current rotation quaternion: (${x}, ${y}, ${z}, ${w})`);
 * });
 * ```
 */
export interface RotationUpdate {
  /**
   * @category Types
   * Device's current rotation represented as a unit quaternion (`{ x, y, z, w }`).
   *
   * Relative to the initial or calibrated reference orientation (where identity is `(0, 0, 0, 1)`).
   * Using quaternions avoids gimbal lock issues commonly encountered with Euler angles (`alpha`, `beta`, `gamma`).
   */
  quaternion: { x: number; y: number; z: number; w: number };
}

/**
 * @category Types
 * Configuration options for the rotation listener.
 *
 * Pass a partial object to {@link deviceRotation.setConfig} to configure behavior.
 *
 * @example
 * ```typescript
 * deviceRotation.setConfig({
 *   pollingRate: 30,
 *   startOnInit: false,
 *   onStart: () => console.log("Orientation tracking active"),
 *   onPermissionDenied: () => console.warn("Orientation permission denied"),
 * });
 * ```
 */
export interface RotationListenerConfig {
  /**
   * Maximum number of orientation updates to emit per second (Hz).
   *
   * Updates will be throttled so they do not exceed this frequency.
   *
   * @defaultValue `60`
   */
  pollingRate: number;

  /**
   * Callback invoked whenever a device orientation permission request is rejected or denied.
   *
   * @defaultValue `() => {}`
   */
  onPermissionDenied: () => void;

  /**
   * Callback invoked whenever device orientation permission is successfully granted.
   *
   * @defaultValue `() => {}`
   */
  onPermissionGranted: () => void;

  /**
   * Callback invoked when orientation listener starts actively listening to events.
   *
   * @defaultValue `() => {}`
   */
  onStart: () => void;

  /**
   * Custom asynchronous function to override the built-in permission request workflow.
   *
   * Can be used to hook into custom UI prompts or authorization flows before invoking
   * `DeviceOrientationEvent.requestPermission()`.
   *
   * @returns A promise resolving to `true` if permission was granted, or `false` otherwise.
   *
   * @example
   * ```typescript
   * customPermissionFunction: async () => {
   *   const res = await (DeviceOrientationEvent as any).requestPermission();
   *   return res === "granted";
   * }
   * ```
   */
  customPermissionFunction?: () => Promise<boolean>;

  /**
   * Whether orientation listening should automatically start as soon as {@link deviceRotation.onUpdate} is registered.
   *
   * If set to `false`, listening must be manually started by calling {@link deviceRotation.start}.
   *
   * @defaultValue `true`
   */
  startOnInit: boolean;
}