angular-three-theatre
Version:
TheatreJS for Angular Three
735 lines (722 loc) • 27.1 kB
TypeScript
import * as _angular_core from '@angular/core';
import { ElementRef } from '@angular/core';
import * as _theatre_core from '@theatre/core';
import { IProjectConfig, ISheet, UnknownShorthandCompoundProps, types, ISequence } from '@theatre/core';
import { NgtsTransformControlsOptions } from 'angular-three-soba/gizmos';
import * as THREE from 'three';
import { IStudio } from '@theatre/studio';
/**
* Component that creates and manages a Theatre.js project.
*
* A Theatre.js project is the top-level container for all animation data.
* It contains sheets, which in turn contain sheet objects that hold animatable properties.
*
* @example
* ```html
* <theatre-project name="my-animation" [config]="{ state: savedState }">
* <ng-container sheet="scene1">
* <!-- sheet objects here -->
* </ng-container>
* </theatre-project>
* ```
*/
declare class TheatreProject {
/**
* The name of the Theatre.js project.
* This name is used to identify the project and must be unique.
*
* @default 'default-theatre-project'
*/
name: _angular_core.InputSignal<string>;
/**
* Configuration options for the Theatre.js project.
* Can include saved state data for restoring animations.
*
* @default {}
*/
config: _angular_core.InputSignal<IProjectConfig>;
/**
* Computed signal containing the Theatre.js project instance.
*/
project: _angular_core.Signal<_theatre_core.IProject>;
/**
* Internal registry of sheets created within this project.
* Tracks sheet instances and their reference counts for cleanup.
*/
sheets: Record<string, [sheet: ISheet, count: number]>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreProject, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TheatreProject, "theatre-project", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
}
/**
* Directive that creates a Theatre.js sheet object for animating properties.
*
* A sheet object is a container for animatable properties within a sheet.
* This directive must be applied to an `ng-template` element and provides
* a structural context with access to the sheet object and its values.
*
* The template context includes:
* - `sheetObject`: The Theatre.js sheet object instance (read-only signal)
* - `values`: Current values of all animated properties (read-only signal)
* - `select()`: Method to select this object in Theatre.js Studio
* - `deselect()`: Method to deselect this object in Theatre.js Studio
*
* @example
* ```html
* <ng-template sheetObject="cube" [sheetObjectProps]="{ opacity: 1 }" let-values="values">
* <ngt-mesh>
* <ngt-mesh-standard-material [opacity]="values().opacity" />
* </ngt-mesh>
* </ng-template>
* ```
*
* @example
* ```html
* <!-- With selection support -->
* <ng-template
* sheetObject="cube"
* [(sheetObjectSelected)]="isSelected"
* let-select="select"
* let-deselect="deselect"
* >
* <ngt-mesh (click)="select()" />
* </ng-template>
* ```
*/
declare class TheatreSheetObject$1 {
/**
* Unique key identifying this sheet object within its parent sheet.
* This key is used by Theatre.js to track and persist animation data.
*/
key: _angular_core.InputSignal<string>;
/**
* Initial properties and their default values for this sheet object.
* These properties will be animatable in Theatre.js Studio.
*
* @default {}
*/
props: _angular_core.InputSignal<UnknownShorthandCompoundProps>;
/**
* Whether to detach (remove) the sheet object when this directive is destroyed.
* When true, the animation data for this object will be removed from the sheet.
*
* @default false
*/
detach: _angular_core.InputSignalWithTransform<boolean, unknown>;
/**
* Two-way bindable signal indicating whether this object is selected in Theatre.js Studio.
*
* @default false
*/
selected: _angular_core.ModelSignal<boolean>;
private templateRef;
private vcr;
private sheet;
private studio;
private store;
private originalSheetObject;
/**
* Signal containing the Theatre.js sheet object instance.
* This is a linked signal that updates when the sheet or key changes.
*/
sheetObject: _angular_core.WritableSignal<_theatre_core.ISheetObject<UnknownShorthandCompoundProps>>;
/**
* Signal containing the current values of all animated properties.
* Updates automatically when Theatre.js values change.
*/
values: _angular_core.WritableSignal<{
[x: string]: any;
}>;
private detached;
private aggregatedProps;
constructor();
/**
* Updates the sheet object with the current aggregated props.
* Detaches the existing object and creates a new one with reconfigured properties.
*/
update(): void;
/**
* Adds new properties to the sheet object.
* The properties are merged with existing properties and the object is reconfigured.
*
* @param props - Properties to add to the sheet object
*/
addProps(props: UnknownShorthandCompoundProps): void;
/**
* Removes properties from the sheet object.
* If all properties are removed and `detach` is true, the object is detached from the sheet.
*
* @param props - Array of property names to remove
*/
removeProps(props: string[]): void;
/**
* Selects this sheet object in Theatre.js Studio.
* Only works when the studio is available.
*/
select(): void;
/**
* Deselects this sheet object in Theatre.js Studio.
* Only deselects if this object is currently selected.
*/
deselect(): void;
/**
* Type guard for the template context.
* Provides type safety for the template variables exposed by this directive.
*
* @param _ - The directive instance
* @param ctx - The template context
* @returns Type predicate for the template context
*/
static ngTemplateContextGuard(_: TheatreSheetObject$1, ctx: unknown): ctx is {
select: TheatreSheetObject$1['select'];
deselect: TheatreSheetObject$1['deselect'];
sheetObject: ReturnType<TheatreSheetObject$1['sheetObject']['asReadonly']>;
values: ReturnType<TheatreSheetObject$1['values']['asReadonly']>;
};
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreSheetObject$1, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TheatreSheetObject$1, "ng-template[sheetObject]", ["sheetObject"], { "key": { "alias": "sheetObject"; "required": true; "isSignal": true; }; "props": { "alias": "sheetObjectProps"; "required": false; "isSignal": true; }; "detach": { "alias": "sheetObjectDetach"; "required": false; "isSignal": true; }; "selected": { "alias": "sheetObjectSelected"; "required": false; "isSignal": true; }; }, { "selected": "sheetObjectSelectedChange"; }, never, never, true, never>;
}
/**
* Type definition for a Theatre.js property transformer.
*
* Transformers are used to convert between Three.js property values and
* Theatre.js animation values. This allows for proper representation
* in the Theatre.js Studio UI (e.g., showing degrees instead of radians).
*
* Based on https://github.com/threlte/threlte/blob/main/packages/theatre/src/lib/sheetObject/transfomers/types.ts
*
* @typeParam Value - The type of the original Three.js property value
* @typeParam TransformedValue - The type of the value used in Theatre.js
*
* @example
* ```typescript
* const myTransformer: TheatreTransformer<number, number> = {
* transform: (value) => types.number(value * 100),
* apply: (target, property, value) => { target[property] = value / 100; }
* };
* ```
*/
type TheatreTransformer<Value = any, TransformedValue = any> = {
/**
* The `transform` function is used to transform the value of a certain
* Three.js objects proerty to a property that Theatre.js can use in an
* `ISheetObject`. To ensure compatibility with the rest of the package, the
* return value must be any one of the functions available at Theatre.js'
* `types`.
*/
transform: (value: Value) => ReturnType<(typeof types)[keyof typeof types]>;
/**
* The `apply` function is used to apply the value to the target. `target` is
* the parent object of the property (usually a Three.js object), `path` is
* the name of the property and `value` is the value to apply.
*/
apply: (target: any, property: string, value: TransformedValue) => void;
};
/**
* Directive that synchronizes Three.js object properties with Theatre.js animations.
*
* This directive allows you to expose specific properties of a Three.js object
* to Theatre.js for animation. It automatically handles property transformation
* (e.g., converting Euler angles to degrees for the UI).
*
* Must be used within a `TheatreSheetObject` context.
*
* @example
* ```html
* <ng-template sheetObject="myMaterial">
* <ngt-mesh-standard-material
* [sync]="material"
* [syncProps]="['opacity', 'roughness', 'metalness']"
* #material
* />
* </ng-template>
* ```
*
* @example
* ```html
* <!-- With custom property mapping -->
* <ng-template sheetObject="myLight">
* <ngt-point-light
* [sync]="light"
* [syncProps]="[
* ['intensity', { label: 'Light Intensity', key: 'lightIntensity' }],
* 'color'
* ]"
* #light
* />
* </ng-template>
* ```
*
* @typeParam TObject - The type of the Three.js object being synchronized
*/
declare class TheatreSheetObjectSync<TObject extends object> {
/**
* The Three.js object to synchronize with Theatre.js.
* Can be an object reference, ElementRef, or a Signal of either.
*/
parent: _angular_core.InputSignal<TObject | ElementRef<TObject> | (() => TObject | ElementRef<TObject> | undefined | null)>;
/**
* Array of property paths to synchronize with Theatre.js.
*
* Each item can be:
* - A string property path (e.g., 'opacity', 'position.x')
* - A tuple of [propertyPath, keyOrOptions] where options can include:
* - `label`: Display label in Theatre.js Studio
* - `key`: Unique key for the property in Theatre.js
* - `transformer`: Custom transformer for the property value
*
* @default []
*/
props: _angular_core.InputSignal<(string | [string, string | {
label?: string;
key?: string;
transformer?: TheatreTransformer;
}])[]>;
private theatreSheetObject;
/**
* Computed signal containing the Theatre.js sheet object instance.
*/
sheetObject: _angular_core.Signal<_theatre_core.ISheetObject<_theatre_core.UnknownShorthandCompoundProps>>;
private studio;
private parentRef;
private resolvedProps;
private propsToAdd;
private propsMapping;
constructor();
/**
* Captures the current values of all synchronized properties from the Three.js object
* and commits them to Theatre.js.
*
* This is useful for "baking" the current state of the Three.js object into the
* Theatre.js animation. Requires Theatre.js Studio to be available.
*/
capture(): void;
/**
* Converts a property path (e.g., 'position.x') to a safe alphanumeric key.
*
* @param propPath - The property path to convert
* @returns A safe alphanumeric key string
*/
private resolvePropertyPath;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreSheetObjectSync<any>, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TheatreSheetObjectSync<any>, "[sync]", ["sync"], { "parent": { "alias": "sync"; "required": true; "isSignal": true; }; "props": { "alias": "syncProps"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
/**
* Component that provides transform controls for animating position, rotation, and scale
* of child Three.js objects via Theatre.js.
*
* When the sheet object is selected in Theatre.js Studio, transform controls appear
* allowing direct manipulation of the object's transform. Changes are captured and
* committed to Theatre.js.
*
* Must be used within a `TheatreSheetObject` context.
*
* @example
* ```html
* <ng-template sheetObject="myCube">
* <theatre-transform>
* <ngt-mesh>
* <ngt-box-geometry />
* <ngt-mesh-standard-material />
* </ngt-mesh>
* </theatre-transform>
* </ng-template>
* ```
*
* @example
* ```html
* <!-- With custom key and options -->
* <ng-template sheetObject="scene">
* <theatre-transform key="cubeTransform" label="Cube" [options]="{ mode: 'rotate' }">
* <ngt-mesh />
* </theatre-transform>
* </ng-template>
* ```
*
* @typeParam TLabel - The type of the label string
*/
declare class TheatreSheetObjectTransform<TLabel extends string | undefined> {
/**
* Display label for the transform properties in Theatre.js Studio.
*/
label: _angular_core.InputSignal<TLabel | undefined>;
/**
* Unique key for grouping the transform properties in Theatre.js.
* If provided, position/rotation/scale will be nested under this key.
*/
key: _angular_core.InputSignal<string | undefined>;
/**
* Options for the transform controls gizmo.
* Allows configuring the transform mode, snap values, and coordinate space.
*
* @default {}
*/
options: _angular_core.InputSignal<Pick<NgtsTransformControlsOptions, "mode" | "translationSnap" | "scaleSnap" | "rotationSnap" | "space">>;
/**
* Reference to the Three.js Group element that wraps the transformed content.
*/
groupRef: _angular_core.Signal<ElementRef<THREE.Group<THREE.Object3DEventMap>>>;
private controlsRef;
private theatreSheetObject;
/**
* Computed signal containing the Theatre.js sheet object instance.
*/
sheetObject: _angular_core.Signal<_theatre_core.ISheetObject<_theatre_core.UnknownShorthandCompoundProps>>;
private studio;
protected selected: _angular_core.Signal<boolean>;
private scrub?;
private positionTransformer;
private rotationTransformer;
private scaleTransformer;
protected onMouseDown(): void;
protected onMouseUp(): void;
protected onChange(): void;
constructor();
private init;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreSheetObjectTransform<any>, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TheatreSheetObjectTransform<any>, "theatre-transform", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "key": { "alias": "key"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
}
/**
* Combined array of sheet object directives for convenient importing.
*
* Includes:
* - `TheatreSheetObject` - Base directive for creating sheet objects
* - `TheatreSheetObjectTransform` - Component for animating transform properties
* - `TheatreSheetObjectSync` - Directive for syncing arbitrary object properties
*
* @example
* ```typescript
* import { TheatreSheetObject } from 'angular-three-theatre';
*
* @Component({
* imports: [TheatreSheetObject],
* template: `
* <ng-template sheetObject="myObject">
* <theatre-transform>
* <ngt-mesh />
* </theatre-transform>
* </ng-template>
* `
* })
* export class MyComponent {}
* ```
*/
declare const TheatreSheetObject: (typeof TheatreSheetObject$1 | typeof TheatreSheetObjectSync | typeof TheatreSheetObjectTransform)[];
/**
* Directive that initializes and manages the Theatre.js Studio.
*
* Theatre.js Studio is a visual editor that allows you to create and edit
* animations directly in the browser. The studio UI is dynamically imported
* to avoid including it in production builds.
*
* This directive must be applied to a `theatre-project` element and provides
* the studio instance via the `THEATRE_STUDIO` injection token.
*
* @example
* ```html
* <!-- Enable studio (default) -->
* <theatre-project studio>
* <ng-container sheet="scene">...</ng-container>
* </theatre-project>
*
* <!-- Conditionally enable/disable studio -->
* <theatre-project [studio]="isDevelopment">
* <ng-container sheet="scene">...</ng-container>
* </theatre-project>
*
* <!-- Disable studio -->
* <theatre-project [studio]="false">
* <ng-container sheet="scene">...</ng-container>
* </theatre-project>
* ```
*/
declare class TheatreStudio {
/**
* Whether the studio UI should be visible.
* When false, the studio UI is hidden but the studio instance remains active.
*
* @default true
*/
enabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
private Studio;
/**
* Read-only signal containing the Theatre.js Studio instance.
* May be null while the studio is being loaded.
*/
studio: _angular_core.Signal<IStudio | null>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreStudio, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TheatreStudio, "theatre-project[studio]", ["studio"], { "enabled": { "alias": "studio"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
/**
* Options for attaching audio to a Theatre.js sequence.
*
* When audio is attached, the sequence playback will be synchronized
* with the audio playback.
*/
interface AttachAudioOptions {
/**
* Either a URL to the audio file (eg "http://localhost:3000/audio.mp3") or an instance of AudioBuffer
*/
source: string | AudioBuffer;
/**
* An optional AudioContext. If not provided, one will be created.
*/
audioContext?: AudioContext;
/**
* An AudioNode to feed the audio into. Will use audioContext.destination if not provided.
*/
destinationNode?: AudioNode;
}
/**
* Configuration options for the TheatreSequence directive.
*
* Extends Theatre.js sequence play options with additional Angular-specific options
* for automatic playback control.
*/
type TheatreSequenceOptions = Parameters<ISequence['play']>[0] & {
/**
* Whether to automatically start playback when the sequence is initialized.
* @default false
*/
autoplay: boolean;
/**
* Whether to automatically pause playback when the directive is destroyed.
* @default false
*/
autopause: boolean;
/**
* Delay in milliseconds before autoplay starts.
* @default 0
*/
delay: number;
/**
* When to reset the sequence position to 0.
* - 'init': Reset when the directive is initialized
* - 'destroy': Reset when the directive is destroyed
* - 'always': Reset on both init and destroy
*/
autoreset?: 'init' | 'destroy' | 'always';
};
/**
* Directive that provides control over a Theatre.js sequence.
*
* A sequence controls the playback of animations within a sheet. This directive
* provides methods to play, pause, and reset the sequence, as well as reactive
* signals for the current position, playing state, and length.
*
* Must be used on an element that also has the `sheet` directive.
*
* @example
* ```html
* <ng-container sheet="scene" [sequence]="{ autoplay: true, rate: 1 }" #seq="sequence">
* <p>Position: {{ seq.position() }}</p>
* <button (click)="seq.play()">Play</button>
* <button (click)="seq.pause()">Pause</button>
* </ng-container>
* ```
*
* @example
* ```html
* <!-- With audio synchronization -->
* <ng-container
* sheet="scene"
* [sequence]="{ autoplay: true }"
* [sequenceAudio]="{ source: '/audio/soundtrack.mp3' }"
* />
* ```
*/
declare class TheatreSequence {
/**
* Sequence configuration options.
* Merged with default options using ngxtension's mergeInputs.
*
* @default { rate: 1, autoplay: false, autopause: false, delay: 0 }
*/
options: _angular_core.InputSignalWithTransform<{
iterationCount?: number;
range?: [from: number, to: number];
rate?: number;
direction?: "reverse" | "normal" | "alternate" | "alternateReverse";
rafDriver?: _theatre_core.IRafDriver;
} & {
/**
* Whether to automatically start playback when the sequence is initialized.
* @default false
*/
autoplay: boolean;
/**
* Whether to automatically pause playback when the directive is destroyed.
* @default false
*/
autopause: boolean;
/**
* Delay in milliseconds before autoplay starts.
* @default 0
*/
delay: number;
/**
* When to reset the sequence position to 0.
* - 'init': Reset when the directive is initialized
* - 'destroy': Reset when the directive is destroyed
* - 'always': Reset on both init and destroy
*/
autoreset?: "init" | "destroy" | "always";
}, "" | Partial<{
iterationCount?: number;
range?: [from: number, to: number];
rate?: number;
direction?: "reverse" | "normal" | "alternate" | "alternateReverse";
rafDriver?: _theatre_core.IRafDriver;
} & {
/**
* Whether to automatically start playback when the sequence is initialized.
* @default false
*/
autoplay: boolean;
/**
* Whether to automatically pause playback when the directive is destroyed.
* @default false
*/
autopause: boolean;
/**
* Delay in milliseconds before autoplay starts.
* @default 0
*/
delay: number;
/**
* When to reset the sequence position to 0.
* - 'init': Reset when the directive is initialized
* - 'destroy': Reset when the directive is destroyed
* - 'always': Reset on both init and destroy
*/
autoreset?: "init" | "destroy" | "always";
}>>;
/**
* Audio options for synchronizing playback with an audio file.
* When provided, the sequence will be synchronized with the audio.
*/
audioOptions: _angular_core.InputSignal<AttachAudioOptions | undefined>;
/**
* Two-way bindable signal for the current playback position in seconds.
*
* @default 0
*/
position: _angular_core.ModelSignal<number>;
/**
* Two-way bindable signal indicating whether the sequence is currently playing.
*
* @default false
*/
playing: _angular_core.ModelSignal<boolean>;
/**
* Two-way bindable signal for the total length of the sequence in seconds.
*
* @default 0
*/
length: _angular_core.ModelSignal<number>;
private playOptions;
private autoplay;
private autopause;
private autoreset;
private delay;
private project;
private sheet;
/**
* Computed signal containing the Theatre.js sequence instance.
*/
sequence: _angular_core.Signal<ISequence>;
constructor();
/**
* Pauses the sequence playback at the current position.
*/
pause(): void;
/**
* Starts or resumes sequence playback.
*
* Waits for the project to be ready before starting playback.
* Options are merged with the configured play options.
*
* @param options - Optional play options that override the configured options
*/
play(options?: Parameters<ISequence['play']>[0]): void;
/**
* Resets the sequence position to 0.
*
* If the sequence was playing before reset, it will continue playing
* from the beginning.
*/
reset(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreSequence, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TheatreSequence, "[sheet][sequence]", ["sequence"], { "options": { "alias": "sequence"; "required": false; "isSignal": true; }; "audioOptions": { "alias": "sequenceAudio"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "playing": { "alias": "playing"; "required": false; "isSignal": true; }; "length": { "alias": "length"; "required": false; "isSignal": true; }; }, { "position": "positionChange"; "playing": "playingChange"; "length": "lengthChange"; }, never, never, true, never>;
}
/**
* Directive that creates and manages a Theatre.js sheet within a project.
*
* A sheet is a container for sheet objects and their animations. Multiple sheets
* can exist within a project, allowing you to organize animations into logical groups.
*
* The directive automatically handles reference counting and cleanup when the
* directive is destroyed.
*
* @example
* ```html
* <theatre-project>
* <ng-container sheet="mainScene">
* <!-- sheet objects here -->
* </ng-container>
* </theatre-project>
* ```
*
* @example
* ```html
* <!-- Using with template reference -->
* <ng-container sheet="mySheet" #sheetRef="sheet">
* {{ sheetRef.sheet().sequence.position }}
* </ng-container>
* ```
*/
declare class TheatreSheet$1 {
/**
* The name of the sheet within the project.
* This name must be unique within the parent project.
*
* @default 'default-theatre-sheet'
*/
name: _angular_core.InputSignalWithTransform<string, string>;
private project;
/**
* Computed signal containing the Theatre.js sheet instance.
* Returns an existing sheet if one with the same name already exists,
* otherwise creates a new sheet.
*/
sheet: _angular_core.Signal<_theatre_core.ISheet>;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TheatreSheet$1, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TheatreSheet$1, "[sheet]", ["sheet"], { "name": { "alias": "sheet"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
/**
* Angular Three Theatre.js integration library
*
* This library provides Angular components and directives for integrating
* Theatre.js animation toolkit with Angular Three applications.
*
* @packageDocumentation
*/
/**
* Combined array of TheatreSheet and TheatreSequence directives for convenient importing.
*
* @example
* ```typescript
* import { TheatreSheet } from 'angular-three-theatre';
*
* @Component({
* imports: [TheatreSheet],
* template: `<ng-container sheet="mySheet" sequence />`
* })
* export class MyComponent {}
* ```
*/
declare const TheatreSheet: readonly [typeof TheatreSheet$1, typeof TheatreSequence];
export { TheatreProject, TheatreSequence, TheatreSheet, TheatreSheet$1 as TheatreSheetImpl, TheatreSheetObject, TheatreSheetObject$1 as TheatreSheetObjectImpl, TheatreSheetObjectSync, TheatreSheetObjectTransform, TheatreStudio };
export type { AttachAudioOptions, TheatreSequenceOptions };