/**
 * Fallback ceiling for {@link createSettleGate}: if a registered source never
 * settles (its swap errored or hung), the gate opens anyway after this many
 * milliseconds so coordination can never be blocked forever. Matches the
 * coordinator's default `ultimateTimeoutMs` and the value the module-global
 * `layoutShiftGate` shipped with.
 */
export declare const SETTLE_SAFETY_TIMEOUT_MS = 10000;
/**
 * A reusable "all sources settled" gate.
 *
 * The module-global page-wide layout-shift gate (`layoutShiftGate`) is one
 * instance; each `StreamController` and `CoordinatedLazy` swap registers with
 * one too. The behavior is the original layout-shift gate's, plus two opt-in
 * completion signals (`expect` / `markLast`) for sources that arrive over time
 * (chunks streaming in across ticks) rather than all within the initial
 * hydration commit.
 *
 * Lifecycle: a source `register()`s and later calls the returned settle
 * function when it reaches its stable state. The gate opens once every
 * registered source has settled (and any completion constraint is met). It
 * opens **once** and never re-closes - a source that registers after the gate
 * has opened adopts the open state rather than re-closing it for everyone
 * ("all sources" means "all present by the initial settle").
 */
export interface SettleGate {
  /**
   * Register a pending source. Returns an idempotent settle function; call it
   * when the source reaches its stable state. Calling it more than once is a
   * no-op. Registering after the gate has already opened returns a no-op settle
   * and does not re-close the gate.
   */
  register(): () => void;
  /**
   * `true` before any source registers (nothing to wait for) and once every
   * registered source has settled and any completion constraint is met.
   */
  isSettled(): boolean;
  /**
   * Resolves once {@link isSettled} is `true`. Returns `null` synchronously
   * when already settled so callers can take a fast path (mirrors the original
   * `whenLayoutShiftsSettled`). Rejects with an `AbortError` if `signal` aborts
   * first, so a superseding wait can be abandoned.
   */
  whenSettled(signal?: AbortSignal): Promise<void> | null;
  /**
   * Declare how many sources will register in total. The gate then holds until
   * at least `count` sources have registered (and all have settled), so it
   * won't open during a momentary lull while later sources are still arriving -
   * e.g. chunks streaming in across separate ticks. This is **known-count**
   * completion.
   *
   * Pass a non-finite value (e.g. `Number.POSITIVE_INFINITY`) to hold the gate
   * open-indefinitely for an unknown-count stream, then call {@link markLast}
   * when the stream ends.
   */
  expect(count: number): void;
  /**
   * Terminal signal for **last-chunk** completion. Once called, the gate opens
   * as soon as every outstanding source has settled, regardless of any `expect`
   * count. Use it to end an unknown-count stream held open via
   * `expect(Infinity)`, or to finish early before an `expect(n)` count is
   * reached. Standalone - it does not require `expect` to have been called.
   */
  markLast(): void;
  /** Reset all state to the initial unarmed gate. Test-only. */
  reset(): void;
}
/**
 * Options for {@link createSettleGate}.
 */
export interface CreateSettleGateOptions {
  /**
   * Fallback ceiling (ms): open the gate even if a registered source never
   * settles.
   * @default SETTLE_SAFETY_TIMEOUT_MS
   */
  safetyTimeoutMs?: number;
  /**
   * Schedule the deferred settle check. Defaults to `queueMicrotask`, which
   * batches a burst of same-tick registrations before declaring the gate
   * settled. Injectable so tests can drive the check synchronously.
   */
  scheduleCheck?: (callback: () => void) => void;
}
/**
 * Create an independent "all sources settled" gate. See {@link SettleGate} for
 * the contract.
 *
 * Isomorphic - it touches only `setTimeout` and the injectable `scheduleCheck`
 * (default `queueMicrotask`), so it runs in tests and during SSR without the
 * DOM. Client-only consumers are responsible for never registering during SSR
 * (the page-wide layout-shift gate is only ever touched on the client for this
 * reason).
 */
export declare function createSettleGate(options?: CreateSettleGateOptions): SettleGate;