import type { ViewModel, ViewModelInstance } from '../specs/ViewModel.nitro';
import type { RiveFile } from '../specs/RiveFile.nitro';
import type { RiveViewRef } from '../index';
interface UseViewModelInstanceBaseParams {
/**
* Create the instance via the async runtime APIs (off the JS thread).
* While creation is in flight the hook reports `isLoading: true` with an
* `undefined` instance. Will become the default in the next major.
*
* Must stay constant for the lifetime of the component — it selects
* between two hook implementations.
*/
async?: boolean;
/**
* If true, throws an error when the instance cannot be obtained.
* This is useful with Error Boundaries and ensures TypeScript knows
* the return value is non-null.
*/
required?: boolean;
/**
* Called when a new instance is created, before the hook exposes it —
* synchronously during render without `async: true`, or right after the
* instance resolves (before it is published) with `async: true`.
* Note: This callback is excluded from deps - changing it won't recreate the instance.
*/
onInit?: (instance: ViewModelInstance) => void;
}
interface UseViewModelInstanceFileBaseParams extends UseViewModelInstanceBaseParams {
/**
* The ViewModel instance name (uses `createInstanceByName()`).
* If not provided, creates the default instance.
*/
instanceName?: string;
}
/**
* Use the ViewModel assigned to the default artboard.
*/
interface UseViewModelInstanceFileDefault extends UseViewModelInstanceFileBaseParams {
artboardName?: never;
viewModelName?: never;
}
/**
* Use the ViewModel assigned to a specific artboard.
*/
interface UseViewModelInstanceFileByArtboard extends UseViewModelInstanceFileBaseParams {
/**
* Get the ViewModel assigned to this artboard.
*/
artboardName: string;
viewModelName?: never;
}
/**
* Use a ViewModel by name (file-wide lookup).
* ViewModels are defined at the file level, not per-artboard.
*/
interface UseViewModelInstanceFileByViewModelName extends UseViewModelInstanceFileBaseParams {
artboardName?: never;
/**
* The name of the ViewModel to use (uses `viewModelByName()`).
* ViewModels are defined at the file level and looked up by name across the entire file.
*/
viewModelName: string;
}
export type UseViewModelInstanceFileParams = UseViewModelInstanceFileDefault | UseViewModelInstanceFileByArtboard | UseViewModelInstanceFileByViewModelName;
export interface UseViewModelInstanceViewModelParams extends UseViewModelInstanceBaseParams {
/**
* The ViewModel instance name (uses `createInstanceByName()`).
* If not provided, creates the default instance.
*/
name?: string;
/**
* Create a new (blank) instance from the ViewModel.
*/
useNew?: boolean;
}
export type UseViewModelInstanceRefParams = UseViewModelInstanceBaseParams;
export type UseViewModelInstanceResult = {
instance: ViewModelInstance;
isLoading: false;
error: null;
} | {
instance: null;
isLoading: false;
error: Error;
} | {
instance: null;
isLoading: false;
error: null;
} | {
instance: undefined;
isLoading: true;
error: null;
};
/**
* Result of {@link useViewModelInstance} when `required: true` is set.
* The `null` (error/absent) case is removed — instead the hook throws once the
* instance resolves to `null`, leaving only the ready and loading states.
*/
export type UseViewModelInstanceRequiredResult = {
instance: ViewModelInstance;
isLoading: false;
error: null;
} | {
instance: undefined;
isLoading: true;
error: null;
};
/**
* Hook for getting a ViewModelInstance from a RiveFile, ViewModel, or RiveViewRef.
*
* Pass `async: true` to create the instance via the async runtime APIs,
* resolving off the JS thread. The instance is then not available on the
* first render — guard on the result:
*
* ```tsx
* const { riveFile, error: fileError } = useRiveFile(require('./animation.riv'));
* const { instance, isLoading, error } = useViewModelInstance(riveFile, { async: true });
* if (fileError || error) return ;
* if (isLoading || !instance) return ;
* // ...
*
* ```
*
* Without `async: true` (deprecated) the instance is created synchronously
* during render via deprecated runtime APIs that block the JS thread. The
* async path will become the default in the next major.
*
* In both modes, a `null` source settles to a terminal
* `{ instance: null, isLoading: false }` while an `undefined` source keeps
* the hook loading. This mirrors {@link useRiveFile} (`riveFile: undefined`
* while loading, `null` on error) and `useRive` (`riveViewRef: undefined`
* until the view is ready, `null` on failure) — so when chaining, check the
* upstream hook's own `error`, since this hook cannot observe why the source
* is absent.
*
* @param source - The RiveFile, ViewModel, or RiveViewRef to get an instance from
* @param params - Configuration for which instance to retrieve
* @returns An object with `instance`, `isLoading`, and `error` (discriminated union)
*
* @example
* ```tsx
* // From RiveFile (get default instance)
* const { riveFile } = useRiveFile(require('./animation.riv'));
* const { instance, isLoading } = useViewModelInstance(riveFile, { async: true });
* ```
*
* @example
* ```tsx
* // From RiveFile with specific instance name
* const { instance } = useViewModelInstance(riveFile, { async: true, instanceName: 'PersonInstance' });
* ```
*
* @example
* ```tsx
* // From RiveFile with specific ViewModel name
* const { instance } = useViewModelInstance(riveFile, { async: true, viewModelName: 'Settings' });
* ```
*
* @example
* ```tsx
* // From RiveFile with specific artboard
* const { instance } = useViewModelInstance(riveFile, { async: true, artboardName: 'MainArtboard' });
* ```
*
* @example
* ```tsx
* // From RiveViewRef (waits for the view's auto-bound instance)
* const { riveViewRef, setHybridRef } = useRive();
* const { instance } = useViewModelInstance(riveViewRef, { async: true });
* ```
*
* @example
* ```tsx
* // Create a new blank instance from ViewModel
* const { instance } = useViewModelInstance(viewModel, { async: true, useNew: true });
* ```
*
* @example
* ```tsx
* // With required: true (throws once resolved to null, use with Error Boundary).
* // Note: instance is still `undefined` while loading — guard on isLoading.
* // The required-narrowed return type applies only when the source's TYPE is
* // non-nullable; with a nullable source (e.g. straight from useRiveFile) the
* // call resolves to the standard overload — the runtime throw still applies.
* const { instance, isLoading } = useViewModelInstance(riveFile, { async: true, required: true });
* ```
*
* @example
* ```tsx
* // With onInit to set initial values before the instance is exposed or bound
* const { instance } = useViewModelInstance(riveFile, {
* async: true,
* onInit: (vmi) => {
* vmi.numberProperty('count')?.set(initialCount);
* }
* });
* ```
*/
export declare function useViewModelInstance(source: RiveFile, params: UseViewModelInstanceFileParams & {
async: true;
required: true;
}): UseViewModelInstanceRequiredResult;
export declare function useViewModelInstance(source: RiveFile | null | undefined, params: UseViewModelInstanceFileParams & {
async: true;
}): UseViewModelInstanceResult;
/** @deprecated Pass `async: true` — without it the instance is created synchronously via deprecated runtime APIs that block the JS thread. `async: true` becomes the default in the next major. If your params object's `async` widened to `boolean`, re-pin it at the call site: `{ ...params, async: true }`. */
export declare function useViewModelInstance(source: RiveFile, params: UseViewModelInstanceFileParams & {
required: true;
}): UseViewModelInstanceRequiredResult;
/** @deprecated Pass `async: true` — without it the instance is created synchronously via deprecated runtime APIs that block the JS thread. `async: true` becomes the default in the next major. If your params object's `async` widened to `boolean`, re-pin it at the call site: `{ ...params, async: true }`. */
export declare function useViewModelInstance(source: RiveFile | null | undefined, params?: UseViewModelInstanceFileParams): UseViewModelInstanceResult;
export declare function useViewModelInstance(source: ViewModel, params: UseViewModelInstanceViewModelParams & {
async: true;
required: true;
}): UseViewModelInstanceRequiredResult;
export declare function useViewModelInstance(source: ViewModel | null | undefined, params: UseViewModelInstanceViewModelParams & {
async: true;
}): UseViewModelInstanceResult;
/** @deprecated Pass `async: true` — without it the instance is created synchronously via deprecated runtime APIs that block the JS thread. `async: true` becomes the default in the next major. If your params object's `async` widened to `boolean`, re-pin it at the call site: `{ ...params, async: true }`. */
export declare function useViewModelInstance(source: ViewModel, params: UseViewModelInstanceViewModelParams & {
required: true;
}): UseViewModelInstanceRequiredResult;
/** @deprecated Pass `async: true` — without it the instance is created synchronously via deprecated runtime APIs that block the JS thread. `async: true` becomes the default in the next major. If your params object's `async` widened to `boolean`, re-pin it at the call site: `{ ...params, async: true }`. */
export declare function useViewModelInstance(source: ViewModel | null | undefined, params?: UseViewModelInstanceViewModelParams): UseViewModelInstanceResult;
export declare function useViewModelInstance(source: RiveViewRef, params: UseViewModelInstanceRefParams & {
async: true;
required: true;
}): UseViewModelInstanceRequiredResult;
export declare function useViewModelInstance(source: RiveViewRef | null | undefined, params: UseViewModelInstanceRefParams & {
async: true;
}): UseViewModelInstanceResult;
/** @deprecated Pass `async: true` — without it the instance is created synchronously via deprecated runtime APIs that block the JS thread. `async: true` becomes the default in the next major. If your params object's `async` widened to `boolean`, re-pin it at the call site: `{ ...params, async: true }`. */
export declare function useViewModelInstance(source: RiveViewRef, params: UseViewModelInstanceRefParams & {
required: true;
}): UseViewModelInstanceRequiredResult;
/** @deprecated Pass `async: true` — without it the instance is created synchronously via deprecated runtime APIs that block the JS thread. `async: true` becomes the default in the next major. If your params object's `async` widened to `boolean`, re-pin it at the call site: `{ ...params, async: true }`. */
export declare function useViewModelInstance(source: RiveViewRef | null | undefined, params?: UseViewModelInstanceRefParams): UseViewModelInstanceResult;
export {};
//# sourceMappingURL=useViewModelInstance.d.ts.map