angular-three-theatre 4.0.0-next.115 → 4.0.0-next.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,23 +7,57 @@ import { Group } from 'three';
7
7
  import { NgtsTransformControls } from 'angular-three-soba/gizmos';
8
8
  import { mergeInputs } from 'ngxtension/inject-inputs';
9
9
 
10
+ /**
11
+ * Component that creates and manages a Theatre.js project.
12
+ *
13
+ * A Theatre.js project is the top-level container for all animation data.
14
+ * It contains sheets, which in turn contain sheet objects that hold animatable properties.
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <theatre-project name="my-animation" [config]="{ state: savedState }">
19
+ * <ng-container sheet="scene1">
20
+ * <!-- sheet objects here -->
21
+ * </ng-container>
22
+ * </theatre-project>
23
+ * ```
24
+ */
10
25
  class TheatreProject {
11
26
  constructor() {
27
+ /**
28
+ * The name of the Theatre.js project.
29
+ * This name is used to identify the project and must be unique.
30
+ *
31
+ * @default 'default-theatre-project'
32
+ */
12
33
  this.name = input('default-theatre-project', ...(ngDevMode ? [{ debugName: "name" }] : []));
34
+ /**
35
+ * Configuration options for the Theatre.js project.
36
+ * Can include saved state data for restoring animations.
37
+ *
38
+ * @default {}
39
+ */
13
40
  this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
41
+ /**
42
+ * Computed signal containing the Theatre.js project instance.
43
+ */
14
44
  this.project = computed(() => getProject(this.name(), this.config()), ...(ngDevMode ? [{ debugName: "project" }] : []));
45
+ /**
46
+ * Internal registry of sheets created within this project.
47
+ * Tracks sheet instances and their reference counts for cleanup.
48
+ */
15
49
  this.sheets = {};
16
50
  effect(() => {
17
51
  const project = this.project();
18
52
  project.ready.then();
19
53
  });
20
54
  }
21
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreProject, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
22
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.7", type: TheatreProject, isStandalone: true, selector: "theatre-project", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
55
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreProject, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
56
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: TheatreProject, isStandalone: true, selector: "theatre-project", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
23
57
  <ng-content />
24
58
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
25
59
  }
26
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreProject, decorators: [{
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreProject, decorators: [{
27
61
  type: Component,
28
62
  args: [{
29
63
  selector: 'theatre-project',
@@ -32,24 +66,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
32
66
  `,
33
67
  changeDetection: ChangeDetectionStrategy.OnPush,
34
68
  }]
35
- }], ctorParameters: () => [] });
69
+ }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
36
70
 
71
+ /**
72
+ * Directive that creates and manages a Theatre.js sheet within a project.
73
+ *
74
+ * A sheet is a container for sheet objects and their animations. Multiple sheets
75
+ * can exist within a project, allowing you to organize animations into logical groups.
76
+ *
77
+ * The directive automatically handles reference counting and cleanup when the
78
+ * directive is destroyed.
79
+ *
80
+ * @example
81
+ * ```html
82
+ * <theatre-project>
83
+ * <ng-container sheet="mainScene">
84
+ * <!-- sheet objects here -->
85
+ * </ng-container>
86
+ * </theatre-project>
87
+ * ```
88
+ *
89
+ * @example
90
+ * ```html
91
+ * <!-- Using with template reference -->
92
+ * <ng-container sheet="mySheet" #sheetRef="sheet">
93
+ * {{ sheetRef.sheet().sequence.position }}
94
+ * </ng-container>
95
+ * ```
96
+ */
37
97
  let TheatreSheet$1 = class TheatreSheet {
38
98
  constructor() {
39
- this.name = input('default-theatre-sheet', ...(ngDevMode ? [{ debugName: "name", transform: (value) => {
40
- if (value === '')
41
- return 'default-theatre-sheet';
42
- return value;
43
- },
44
- alias: 'sheet' }] : [{
45
- transform: (value) => {
46
- if (value === '')
47
- return 'default-theatre-sheet';
48
- return value;
49
- },
50
- alias: 'sheet',
51
- }]));
99
+ /**
100
+ * The name of the sheet within the project.
101
+ * This name must be unique within the parent project.
102
+ *
103
+ * @default 'default-theatre-sheet'
104
+ */
105
+ this.name = input('default-theatre-sheet', { ...(ngDevMode ? { debugName: "name" } : {}), transform: (value) => {
106
+ if (value === '')
107
+ return 'default-theatre-sheet';
108
+ return value;
109
+ },
110
+ alias: 'sheet' });
52
111
  this.project = inject(TheatreProject);
112
+ /**
113
+ * Computed signal containing the Theatre.js sheet instance.
114
+ * Returns an existing sheet if one with the same name already exists,
115
+ * otherwise creates a new sheet.
116
+ */
53
117
  this.sheet = computed(() => {
54
118
  const name = this.name();
55
119
  const existing = this.project.sheets[name] || [];
@@ -73,22 +137,99 @@ let TheatreSheet$1 = class TheatreSheet {
73
137
  }
74
138
  });
75
139
  }
76
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
77
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: TheatreSheet, isStandalone: true, selector: "[sheet]", inputs: { name: { classPropertyName: "name", publicName: "sheet", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["sheet"], ngImport: i0 }); }
140
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
141
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSheet, isStandalone: true, selector: "[sheet]", inputs: { name: { classPropertyName: "name", publicName: "sheet", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["sheet"], ngImport: i0 }); }
78
142
  };
79
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheet$1, decorators: [{
143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheet$1, decorators: [{
80
144
  type: Directive,
81
145
  args: [{ selector: '[sheet]', exportAs: 'sheet' }]
82
- }], ctorParameters: () => [] });
146
+ }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheet", required: false }] }] } });
83
147
 
148
+ /**
149
+ * Injection token for accessing the Theatre.js Studio instance.
150
+ *
151
+ * The studio provides a visual editor for creating and editing animations.
152
+ * This token is provided by the TheatreStudio directive and can be injected
153
+ * into child components.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * import { THEATRE_STUDIO } from 'angular-three-theatre';
158
+ *
159
+ * @Component({...})
160
+ * export class MyComponent {
161
+ * private studio = inject(THEATRE_STUDIO, { optional: true });
162
+ *
163
+ * selectObject() {
164
+ * this.studio()?.setSelection([mySheetObject]);
165
+ * }
166
+ * }
167
+ * ```
168
+ */
84
169
  const THEATRE_STUDIO = new InjectionToken('Theatre Studio');
85
170
 
171
+ /**
172
+ * Directive that creates a Theatre.js sheet object for animating properties.
173
+ *
174
+ * A sheet object is a container for animatable properties within a sheet.
175
+ * This directive must be applied to an `ng-template` element and provides
176
+ * a structural context with access to the sheet object and its values.
177
+ *
178
+ * The template context includes:
179
+ * - `sheetObject`: The Theatre.js sheet object instance (read-only signal)
180
+ * - `values`: Current values of all animated properties (read-only signal)
181
+ * - `select()`: Method to select this object in Theatre.js Studio
182
+ * - `deselect()`: Method to deselect this object in Theatre.js Studio
183
+ *
184
+ * @example
185
+ * ```html
186
+ * <ng-template sheetObject="cube" [sheetObjectProps]="{ opacity: 1 }" let-values="values">
187
+ * <ngt-mesh>
188
+ * <ngt-mesh-standard-material [opacity]="values().opacity" />
189
+ * </ngt-mesh>
190
+ * </ng-template>
191
+ * ```
192
+ *
193
+ * @example
194
+ * ```html
195
+ * <!-- With selection support -->
196
+ * <ng-template
197
+ * sheetObject="cube"
198
+ * [(sheetObjectSelected)]="isSelected"
199
+ * let-select="select"
200
+ * let-deselect="deselect"
201
+ * >
202
+ * <ngt-mesh (click)="select()" />
203
+ * </ng-template>
204
+ * ```
205
+ */
86
206
  let TheatreSheetObject$1 = class TheatreSheetObject {
87
207
  constructor() {
88
- this.key = input.required(...(ngDevMode ? [{ debugName: "key", alias: 'sheetObject' }] : [{ alias: 'sheetObject' }]));
89
- this.props = input({}, ...(ngDevMode ? [{ debugName: "props", alias: 'sheetObjectProps' }] : [{ alias: 'sheetObjectProps' }]));
90
- this.detach = input(false, ...(ngDevMode ? [{ debugName: "detach", transform: booleanAttribute, alias: 'sheetObjectDetach' }] : [{ transform: booleanAttribute, alias: 'sheetObjectDetach' }]));
91
- this.selected = model(false, ...(ngDevMode ? [{ debugName: "selected", alias: 'sheetObjectSelected' }] : [{ alias: 'sheetObjectSelected' }]));
208
+ /**
209
+ * Unique key identifying this sheet object within its parent sheet.
210
+ * This key is used by Theatre.js to track and persist animation data.
211
+ */
212
+ this.key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}), alias: 'sheetObject' });
213
+ /**
214
+ * Initial properties and their default values for this sheet object.
215
+ * These properties will be animatable in Theatre.js Studio.
216
+ *
217
+ * @default {}
218
+ */
219
+ this.props = input({}, { ...(ngDevMode ? { debugName: "props" } : {}), alias: 'sheetObjectProps' });
220
+ /**
221
+ * Whether to detach (remove) the sheet object when this directive is destroyed.
222
+ * When true, the animation data for this object will be removed from the sheet.
223
+ *
224
+ * @default false
225
+ */
226
+ this.detach = input(false, { ...(ngDevMode ? { debugName: "detach" } : {}), transform: booleanAttribute, alias: 'sheetObjectDetach' });
227
+ /**
228
+ * Two-way bindable signal indicating whether this object is selected in Theatre.js Studio.
229
+ *
230
+ * @default false
231
+ */
232
+ this.selected = model(false, { ...(ngDevMode ? { debugName: "selected" } : {}), alias: 'sheetObjectSelected' });
92
233
  this.templateRef = inject(TemplateRef);
93
234
  this.vcr = inject(ViewContainerRef);
94
235
  this.sheet = inject(TheatreSheet$1);
@@ -98,8 +239,16 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
98
239
  const sheet = this.sheet.sheet();
99
240
  return sheet.object(this.key(), untracked(this.props), { reconfigure: true });
100
241
  }, ...(ngDevMode ? [{ debugName: "originalSheetObject" }] : []));
101
- this.sheetObject = linkedSignal(this.originalSheetObject);
102
- this.values = linkedSignal(() => this.sheetObject().value);
242
+ /**
243
+ * Signal containing the Theatre.js sheet object instance.
244
+ * This is a linked signal that updates when the sheet or key changes.
245
+ */
246
+ this.sheetObject = linkedSignal(this.originalSheetObject, ...(ngDevMode ? [{ debugName: "sheetObject" }] : []));
247
+ /**
248
+ * Signal containing the current values of all animated properties.
249
+ * Updates automatically when Theatre.js values change.
250
+ */
251
+ this.values = linkedSignal(() => this.sheetObject().value, ...(ngDevMode ? [{ debugName: "values" }] : []));
103
252
  this.detached = false;
104
253
  this.aggregatedProps = {};
105
254
  effect(() => {
@@ -142,6 +291,10 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
142
291
  }
143
292
  });
144
293
  }
294
+ /**
295
+ * Updates the sheet object with the current aggregated props.
296
+ * Detaches the existing object and creates a new one with reconfigured properties.
297
+ */
145
298
  update() {
146
299
  if (this.detached)
147
300
  return;
@@ -149,10 +302,22 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
149
302
  sheet.detachObject(key);
150
303
  this.sheetObject.set(sheet.object(key, this.aggregatedProps, { reconfigure: true }));
151
304
  }
305
+ /**
306
+ * Adds new properties to the sheet object.
307
+ * The properties are merged with existing properties and the object is reconfigured.
308
+ *
309
+ * @param props - Properties to add to the sheet object
310
+ */
152
311
  addProps(props) {
153
312
  this.aggregatedProps = { ...this.aggregatedProps, ...props };
154
313
  this.update();
155
314
  }
315
+ /**
316
+ * Removes properties from the sheet object.
317
+ * If all properties are removed and `detach` is true, the object is detached from the sheet.
318
+ *
319
+ * @param props - Array of property names to remove
320
+ */
156
321
  removeProps(props) {
157
322
  const [detach, sheet, key] = [untracked(this.detach), untracked(this.sheet.sheet), untracked(this.key)];
158
323
  // remove props from sheet object
@@ -171,12 +336,20 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
171
336
  this.update();
172
337
  }
173
338
  }
339
+ /**
340
+ * Selects this sheet object in Theatre.js Studio.
341
+ * Only works when the studio is available.
342
+ */
174
343
  select() {
175
344
  const studio = this.studio?.();
176
345
  if (!studio)
177
346
  return;
178
347
  studio.setSelection([this.sheetObject()]);
179
348
  }
349
+ /**
350
+ * Deselects this sheet object in Theatre.js Studio.
351
+ * Only deselects if this object is currently selected.
352
+ */
180
353
  deselect() {
181
354
  const studio = this.studio?.();
182
355
  if (!studio)
@@ -185,22 +358,64 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
185
358
  studio.setSelection([]);
186
359
  }
187
360
  }
361
+ /**
362
+ * Type guard for the template context.
363
+ * Provides type safety for the template variables exposed by this directive.
364
+ *
365
+ * @param _ - The directive instance
366
+ * @param ctx - The template context
367
+ * @returns Type predicate for the template context
368
+ */
188
369
  static ngTemplateContextGuard(_, ctx) {
189
370
  return true;
190
371
  }
191
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheetObject, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
192
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: TheatreSheetObject, isStandalone: true, selector: "ng-template[sheetObject]", inputs: { key: { classPropertyName: "key", publicName: "sheetObject", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "sheetObjectProps", isSignal: true, isRequired: false, transformFunction: null }, detach: { classPropertyName: "detach", publicName: "sheetObjectDetach", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "sheetObjectSelected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "sheetObjectSelectedChange" }, exportAs: ["sheetObject"], ngImport: i0 }); }
372
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObject, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
373
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSheetObject, isStandalone: true, selector: "ng-template[sheetObject]", inputs: { key: { classPropertyName: "key", publicName: "sheetObject", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "sheetObjectProps", isSignal: true, isRequired: false, transformFunction: null }, detach: { classPropertyName: "detach", publicName: "sheetObjectDetach", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "sheetObjectSelected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "sheetObjectSelectedChange" }, exportAs: ["sheetObject"], ngImport: i0 }); }
193
374
  };
194
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheetObject$1, decorators: [{
375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObject$1, decorators: [{
195
376
  type: Directive,
196
377
  args: [{ selector: 'ng-template[sheetObject]', exportAs: 'sheetObject' }]
197
- }], ctorParameters: () => [] });
378
+ }], ctorParameters: () => [], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObject", required: true }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObjectProps", required: false }] }], detach: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObjectDetach", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObjectSelected", required: false }] }, { type: i0.Output, args: ["sheetObjectSelectedChange"] }] } });
198
379
 
380
+ /**
381
+ * Factory function for creating a Theatre.js transformer.
382
+ *
383
+ * This is a convenience function that provides type inference for transformer creation.
384
+ *
385
+ * @param transformer - The transformer configuration object
386
+ * @returns The same transformer object (identity function with type inference)
387
+ *
388
+ * @example
389
+ * ```typescript
390
+ * import { createTransformer } from 'angular-three-theatre';
391
+ * import { types } from '@theatre/core';
392
+ *
393
+ * export const percentage = createTransformer({
394
+ * transform: (value) => types.number(value * 100, { range: [0, 100] }),
395
+ * apply: (target, property, value) => { target[property] = value / 100; }
396
+ * });
397
+ * ```
398
+ */
199
399
  function createTransformer(transformer) {
200
400
  return transformer;
201
401
  }
202
402
 
203
403
  const _color = new THREE.Color();
404
+ /**
405
+ * Transformer for Three.js Color objects.
406
+ *
407
+ * Converts Three.js Color to Theatre.js RGBA format for the color picker UI.
408
+ * Uses sRGB color space for accurate color representation.
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * import { color } from 'angular-three-theatre';
413
+ *
414
+ * // Used automatically for Color properties, or manually:
415
+ * [sync]="material"
416
+ * [syncProps]="[['emissive', { transformer: color }]]"
417
+ * ```
418
+ */
204
419
  const color = createTransformer({
205
420
  transform(value) {
206
421
  value.getRGB(_color, THREE.SRGBColorSpace);
@@ -211,6 +426,21 @@ const color = createTransformer({
211
426
  },
212
427
  });
213
428
 
429
+ /**
430
+ * Transformer for radian values that displays as degrees in the UI.
431
+ *
432
+ * Converts between radians (used by Three.js) and degrees (more intuitive for users).
433
+ * Used automatically for rotation.x, rotation.y, and rotation.z properties.
434
+ *
435
+ * @example
436
+ * ```typescript
437
+ * import { degrees } from 'angular-three-theatre';
438
+ *
439
+ * // Used automatically for rotation components, or manually:
440
+ * [sync]="camera"
441
+ * [syncProps]="[['fov', { transformer: degrees }]]"
442
+ * ```
443
+ */
214
444
  const degrees = createTransformer({
215
445
  transform(target) {
216
446
  return types.number(target * THREE.MathUtils.RAD2DEG);
@@ -220,6 +450,23 @@ const degrees = createTransformer({
220
450
  },
221
451
  });
222
452
 
453
+ /**
454
+ * Transformer for Three.js Euler rotation objects.
455
+ *
456
+ * Converts Euler angles from radians to degrees for display in Theatre.js Studio.
457
+ * Creates a compound property with x, y, z components shown in degrees.
458
+ *
459
+ * Used automatically for properties where `isEuler` is true (e.g., Object3D.rotation).
460
+ *
461
+ * @example
462
+ * ```typescript
463
+ * import { euler } from 'angular-three-theatre';
464
+ *
465
+ * // Used automatically for Euler properties, or manually:
466
+ * [sync]="mesh"
467
+ * [syncProps]="[['rotation', { transformer: euler }]]"
468
+ * ```
469
+ */
223
470
  const euler = createTransformer({
224
471
  transform(value) {
225
472
  return types.compound({
@@ -235,6 +482,26 @@ const euler = createTransformer({
235
482
  },
236
483
  });
237
484
 
485
+ /**
486
+ * Generic fallback transformer that handles common JavaScript types.
487
+ *
488
+ * Automatically detects the value type and applies the appropriate Theatre.js type:
489
+ * - Numbers → `types.number` (Infinity converted to MAX_VALUE)
490
+ * - Strings → `types.string`
491
+ * - Booleans → `types.boolean`
492
+ * - Objects → `types.compound` (spreads properties)
493
+ *
494
+ * Used as the default transformer when no specific transformer matches.
495
+ *
496
+ * @example
497
+ * ```typescript
498
+ * import { generic } from 'angular-three-theatre';
499
+ *
500
+ * // Explicitly use generic transformer:
501
+ * [sync]="mesh"
502
+ * [syncProps]="[['customProperty', { transformer: generic }]]"
503
+ * ```
504
+ */
238
505
  const generic = createTransformer({
239
506
  transform(value) {
240
507
  if (typeof value === 'number') {
@@ -258,6 +525,22 @@ const generic = createTransformer({
258
525
  },
259
526
  });
260
527
 
528
+ /**
529
+ * Transformer for normalized values in the 0-1 range.
530
+ *
531
+ * Creates a number input with a slider constrained to the 0-1 range.
532
+ * Used automatically for material properties like opacity, roughness,
533
+ * metalness, transmission, and color components (r, g, b).
534
+ *
535
+ * @example
536
+ * ```typescript
537
+ * import { normalized } from 'angular-three-theatre';
538
+ *
539
+ * // Used automatically for common properties, or manually:
540
+ * [sync]="material"
541
+ * [syncProps]="[['customNormalizedValue', { transformer: normalized }]]"
542
+ * ```
543
+ */
261
544
  const normalized = createTransformer({
262
545
  transform(value) {
263
546
  return types.number(value, { range: [0, 1] });
@@ -267,6 +550,23 @@ const normalized = createTransformer({
267
550
  },
268
551
  });
269
552
 
553
+ /**
554
+ * Transformer for Three.js material side property.
555
+ *
556
+ * Converts between Three.js side constants (FrontSide, BackSide, DoubleSide)
557
+ * and a switch UI in Theatre.js Studio with human-readable labels.
558
+ *
559
+ * Used automatically for the `side` property on materials.
560
+ *
561
+ * @example
562
+ * ```typescript
563
+ * import { side } from 'angular-three-theatre';
564
+ *
565
+ * // Used automatically for material.side, or manually:
566
+ * [sync]="material"
567
+ * [syncProps]="[['side', { transformer: side }]]"
568
+ * ```
569
+ */
270
570
  const side = createTransformer({
271
571
  transform(value) {
272
572
  // TODO: fix this type
@@ -277,9 +577,42 @@ const side = createTransformer({
277
577
  },
278
578
  });
279
579
 
580
+ /**
581
+ * Checks if a property path matches a pattern exactly or ends with the pattern.
582
+ *
583
+ * @param fullPropertyPath - The full property path (e.g., 'material.opacity')
584
+ * @param pattern - The pattern to match (e.g., 'opacity')
585
+ * @returns True if the path matches or ends with the pattern
586
+ */
280
587
  function isFullOrEndingPattern(fullPropertyPath, pattern) {
281
588
  return fullPropertyPath.endsWith(`.${pattern}`) || fullPropertyPath === pattern;
282
589
  }
590
+ /**
591
+ * Determines the appropriate transformer for a Three.js property based on its type and path.
592
+ *
593
+ * This function automatically selects the best transformer for common Three.js properties:
594
+ * - Euler rotations → `euler` transformer (degrees display)
595
+ * - Color values → `color` transformer (RGBA picker)
596
+ * - Rotation components (x, y, z) → `degrees` transformer
597
+ * - Color components (r, g, b) → `normalized` transformer (0-1 range)
598
+ * - Material properties (opacity, roughness, metalness, transmission) → `normalized` transformer
599
+ * - Side property → `side` transformer (Front/Back/Double switch)
600
+ * - All others → `generic` transformer
601
+ *
602
+ * @param target - The parent object containing the property
603
+ * @param path - The property name on the target
604
+ * @param fullPropertyPath - The full dot-notation path to the property
605
+ * @returns The appropriate transformer for the property
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * import { getDefaultTransformer } from 'angular-three-theatre';
610
+ *
611
+ * const mesh = new THREE.Mesh();
612
+ * const transformer = getDefaultTransformer(mesh, 'rotation', 'rotation');
613
+ * // Returns the euler transformer
614
+ * ```
615
+ */
283
616
  function getDefaultTransformer(target, path, fullPropertyPath) {
284
617
  const property = target[path];
285
618
  if (property.isEuler)
@@ -312,13 +645,67 @@ function getDefaultTransformer(target, path, fullPropertyPath) {
312
645
  }
313
646
 
314
647
  const updateProjectionMatrixKeys = ['fov', 'near', 'far', 'zoom', 'left', 'right', 'top', 'bottom', 'aspect'];
648
+ /**
649
+ * Directive that synchronizes Three.js object properties with Theatre.js animations.
650
+ *
651
+ * This directive allows you to expose specific properties of a Three.js object
652
+ * to Theatre.js for animation. It automatically handles property transformation
653
+ * (e.g., converting Euler angles to degrees for the UI).
654
+ *
655
+ * Must be used within a `TheatreSheetObject` context.
656
+ *
657
+ * @example
658
+ * ```html
659
+ * <ng-template sheetObject="myMaterial">
660
+ * <ngt-mesh-standard-material
661
+ * [sync]="material"
662
+ * [syncProps]="['opacity', 'roughness', 'metalness']"
663
+ * #material
664
+ * />
665
+ * </ng-template>
666
+ * ```
667
+ *
668
+ * @example
669
+ * ```html
670
+ * <!-- With custom property mapping -->
671
+ * <ng-template sheetObject="myLight">
672
+ * <ngt-point-light
673
+ * [sync]="light"
674
+ * [syncProps]="[
675
+ * ['intensity', { label: 'Light Intensity', key: 'lightIntensity' }],
676
+ * 'color'
677
+ * ]"
678
+ * #light
679
+ * />
680
+ * </ng-template>
681
+ * ```
682
+ *
683
+ * @typeParam TObject - The type of the Three.js object being synchronized
684
+ */
315
685
  class TheatreSheetObjectSync {
316
686
  constructor() {
317
- this.parent = input.required(...(ngDevMode ? [{ debugName: "parent", alias: 'sync' }] : [{
318
- alias: 'sync',
319
- }]));
320
- this.props = input([], ...(ngDevMode ? [{ debugName: "props", alias: 'syncProps' }] : [{ alias: 'syncProps' }]));
687
+ /**
688
+ * The Three.js object to synchronize with Theatre.js.
689
+ * Can be an object reference, ElementRef, or a function returning either.
690
+ */
691
+ this.parent = input.required({ ...(ngDevMode ? { debugName: "parent" } : {}), alias: 'sync' });
692
+ /**
693
+ * Array of property paths to synchronize with Theatre.js.
694
+ *
695
+ * Each item can be:
696
+ * - A string property path (e.g., 'opacity', 'position.x')
697
+ * - A tuple of [propertyPath, keyOrOptions] where options can include:
698
+ * - `label`: Display label in Theatre.js Studio
699
+ * - `key`: Unique key for the property in Theatre.js
700
+ * - `transformer`: Custom transformer for the property value
701
+ *
702
+ * @default []
703
+ */
704
+ this.props = input([], { ...(ngDevMode ? { debugName: "props" } : {}), alias: 'syncProps' });
321
705
  this.theatreSheetObject = inject(TheatreSheetObject$1);
706
+ /**
707
+ * Computed signal containing the Theatre.js sheet object instance.
708
+ */
322
709
  this.sheetObject = computed(() => this.theatreSheetObject.sheetObject(), ...(ngDevMode ? [{ debugName: "sheetObject" }] : []));
323
710
  this.studio = inject(THEATRE_STUDIO, { optional: true });
324
711
  this.parentRef = computed(() => {
@@ -398,6 +785,13 @@ class TheatreSheetObjectSync {
398
785
  this.theatreSheetObject.removeProps(Object.keys(this.propsMapping));
399
786
  });
400
787
  }
788
+ /**
789
+ * Captures the current values of all synchronized properties from the Three.js object
790
+ * and commits them to Theatre.js.
791
+ *
792
+ * This is useful for "baking" the current state of the Three.js object into the
793
+ * Theatre.js animation. Requires Theatre.js Studio to be available.
794
+ */
401
795
  capture() {
402
796
  const studio = this.studio?.();
403
797
  if (!studio)
@@ -423,6 +817,12 @@ class TheatreSheetObjectSync {
423
817
  });
424
818
  scrub.commit();
425
819
  }
820
+ /**
821
+ * Converts a property path (e.g., 'position.x') to a safe alphanumeric key.
822
+ *
823
+ * @param propPath - The property path to convert
824
+ * @returns A safe alphanumeric key string
825
+ */
426
826
  resolvePropertyPath(propPath) {
427
827
  return (propPath
428
828
  // make the label alphanumeric by first removing dots (fundamental feature for pierced props)
@@ -432,14 +832,48 @@ class TheatreSheetObjectSync {
432
832
  // convert to safe alphanumeric characters without dashes
433
833
  .replace(/[^a-zA-Z0-9]/g, ''));
434
834
  }
435
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheetObjectSync, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
436
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: TheatreSheetObjectSync, isStandalone: true, selector: "[sync]", inputs: { parent: { classPropertyName: "parent", publicName: "sync", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "syncProps", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["sync"], ngImport: i0 }); }
835
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectSync, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
836
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSheetObjectSync, isStandalone: true, selector: "[sync]", inputs: { parent: { classPropertyName: "parent", publicName: "sync", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "syncProps", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["sync"], ngImport: i0 }); }
437
837
  }
438
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheetObjectSync, decorators: [{
838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectSync, decorators: [{
439
839
  type: Directive,
440
840
  args: [{ selector: '[sync]', exportAs: 'sync' }]
441
- }], ctorParameters: () => [] });
841
+ }], ctorParameters: () => [], propDecorators: { parent: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: true }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "syncProps", required: false }] }] } });
442
842
 
843
+ /**
844
+ * Component that provides transform controls for animating position, rotation, and scale
845
+ * of child Three.js objects via Theatre.js.
846
+ *
847
+ * When the sheet object is selected in Theatre.js Studio, transform controls appear
848
+ * allowing direct manipulation of the object's transform. Changes are captured and
849
+ * committed to Theatre.js.
850
+ *
851
+ * Must be used within a `TheatreSheetObject` context.
852
+ *
853
+ * @example
854
+ * ```html
855
+ * <ng-template sheetObject="myCube">
856
+ * <theatre-transform>
857
+ * <ngt-mesh>
858
+ * <ngt-box-geometry />
859
+ * <ngt-mesh-standard-material />
860
+ * </ngt-mesh>
861
+ * </theatre-transform>
862
+ * </ng-template>
863
+ * ```
864
+ *
865
+ * @example
866
+ * ```html
867
+ * <!-- With custom key and options -->
868
+ * <ng-template sheetObject="scene">
869
+ * <theatre-transform key="cubeTransform" label="Cube" [options]="{ mode: 'rotate' }">
870
+ * <ngt-mesh />
871
+ * </theatre-transform>
872
+ * </ng-template>
873
+ * ```
874
+ *
875
+ * @typeParam TLabel - The type of the label string
876
+ */
443
877
  class TheatreSheetObjectTransform {
444
878
  onMouseDown() {
445
879
  if (!this.studio)
@@ -474,12 +908,31 @@ class TheatreSheetObjectTransform {
474
908
  });
475
909
  }
476
910
  constructor() {
911
+ /**
912
+ * Display label for the transform properties in Theatre.js Studio.
913
+ */
477
914
  this.label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
915
+ /**
916
+ * Unique key for grouping the transform properties in Theatre.js.
917
+ * If provided, position/rotation/scale will be nested under this key.
918
+ */
478
919
  this.key = input(...(ngDevMode ? [undefined, { debugName: "key" }] : []));
920
+ /**
921
+ * Options for the transform controls gizmo.
922
+ * Allows configuring the transform mode, snap values, and coordinate space.
923
+ *
924
+ * @default {}
925
+ */
479
926
  this.options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : []));
927
+ /**
928
+ * Reference to the Three.js Group element that wraps the transformed content.
929
+ */
480
930
  this.groupRef = viewChild.required('group');
481
931
  this.controlsRef = viewChild(NgtsTransformControls, ...(ngDevMode ? [{ debugName: "controlsRef" }] : []));
482
932
  this.theatreSheetObject = inject(TheatreSheetObject$1);
933
+ /**
934
+ * Computed signal containing the Theatre.js sheet object instance.
935
+ */
483
936
  this.sheetObject = computed(() => this.theatreSheetObject.sheetObject(), ...(ngDevMode ? [{ debugName: "sheetObject" }] : []));
484
937
  this.studio = inject(THEATRE_STUDIO, { optional: true });
485
938
  this.selected = this.theatreSheetObject.selected.asReadonly();
@@ -559,8 +1012,8 @@ class TheatreSheetObjectTransform {
559
1012
  this.theatreSheetObject.addProps({ position, rotation, scale });
560
1013
  }
561
1014
  }
562
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheetObjectTransform, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
563
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: TheatreSheetObjectTransform, isStandalone: true, selector: "theatre-transform", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "groupRef", first: true, predicate: ["group"], descendants: true, isSignal: true }, { propertyName: "controlsRef", first: true, predicate: NgtsTransformControls, descendants: true, isSignal: true }], ngImport: i0, template: `
1015
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectTransform, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1016
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TheatreSheetObjectTransform, isStandalone: true, selector: "theatre-transform", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "groupRef", first: true, predicate: ["group"], descendants: true, isSignal: true }, { propertyName: "controlsRef", first: true, predicate: NgtsTransformControls, descendants: true, isSignal: true }], ngImport: i0, template: `
564
1017
  @if (selected()) {
565
1018
  <ngts-transform-controls [object]="$any(group)" [options]="options()" />
566
1019
  }
@@ -570,7 +1023,7 @@ class TheatreSheetObjectTransform {
570
1023
  </ngt-group>
571
1024
  `, isInline: true, dependencies: [{ kind: "component", type: NgtsTransformControls, selector: "ngts-transform-controls", inputs: ["object", "options"], outputs: ["change", "mouseDown", "mouseUp", "objectChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
572
1025
  }
573
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSheetObjectTransform, decorators: [{
1026
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectTransform, decorators: [{
574
1027
  type: Component,
575
1028
  args: [{
576
1029
  selector: 'theatre-transform',
@@ -587,14 +1040,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
587
1040
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
588
1041
  changeDetection: ChangeDetectionStrategy.OnPush,
589
1042
  }]
590
- }], ctorParameters: () => [] });
1043
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], groupRef: [{ type: i0.ViewChild, args: ['group', { isSignal: true }] }], controlsRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NgtsTransformControls), { isSignal: true }] }] } });
591
1044
 
1045
+ /**
1046
+ * Combined array of sheet object directives for convenient importing.
1047
+ *
1048
+ * Includes:
1049
+ * - `TheatreSheetObject` - Base directive for creating sheet objects
1050
+ * - `TheatreSheetObjectTransform` - Component for animating transform properties
1051
+ * - `TheatreSheetObjectSync` - Directive for syncing arbitrary object properties
1052
+ *
1053
+ * @example
1054
+ * ```typescript
1055
+ * import { TheatreSheetObject } from 'angular-three-theatre';
1056
+ *
1057
+ * @Component({
1058
+ * imports: [TheatreSheetObject],
1059
+ * template: `
1060
+ * <ng-template sheetObject="myObject">
1061
+ * <theatre-transform>
1062
+ * <ngt-mesh />
1063
+ * </theatre-transform>
1064
+ * </ng-template>
1065
+ * `
1066
+ * })
1067
+ * export class MyComponent {}
1068
+ * ```
1069
+ */
592
1070
  const TheatreSheetObject = [TheatreSheetObject$1, TheatreSheetObjectTransform, TheatreSheetObjectSync];
593
1071
 
1072
+ /**
1073
+ * Directive that initializes and manages the Theatre.js Studio.
1074
+ *
1075
+ * Theatre.js Studio is a visual editor that allows you to create and edit
1076
+ * animations directly in the browser. The studio UI is dynamically imported
1077
+ * to avoid including it in production builds.
1078
+ *
1079
+ * This directive must be applied to a `theatre-project` element and provides
1080
+ * the studio instance via the `THEATRE_STUDIO` injection token.
1081
+ *
1082
+ * @example
1083
+ * ```html
1084
+ * <!-- Enable studio (default) -->
1085
+ * <theatre-project studio>
1086
+ * <ng-container sheet="scene">...</ng-container>
1087
+ * </theatre-project>
1088
+ *
1089
+ * <!-- Conditionally enable/disable studio -->
1090
+ * <theatre-project [studio]="isDevelopment">
1091
+ * <ng-container sheet="scene">...</ng-container>
1092
+ * </theatre-project>
1093
+ *
1094
+ * <!-- Disable studio -->
1095
+ * <theatre-project [studio]="false">
1096
+ * <ng-container sheet="scene">...</ng-container>
1097
+ * </theatre-project>
1098
+ * ```
1099
+ */
594
1100
  class TheatreStudio {
595
1101
  constructor() {
596
- this.enabled = input(true, ...(ngDevMode ? [{ debugName: "enabled", alias: 'studio', transform: booleanAttribute }] : [{ alias: 'studio', transform: booleanAttribute }]));
1102
+ /**
1103
+ * Whether the studio UI should be visible.
1104
+ * When false, the studio UI is hidden but the studio instance remains active.
1105
+ *
1106
+ * @default true
1107
+ */
1108
+ this.enabled = input(true, { ...(ngDevMode ? { debugName: "enabled" } : {}), alias: 'studio', transform: booleanAttribute });
597
1109
  this.Studio = signal(null, ...(ngDevMode ? [{ debugName: "Studio" }] : []));
1110
+ /**
1111
+ * Read-only signal containing the Theatre.js Studio instance.
1112
+ * May be null while the studio is being loaded.
1113
+ */
598
1114
  this.studio = this.Studio.asReadonly();
599
1115
  import('@theatre/studio').then((m) => {
600
1116
  const Studio = 'default' in m.default ? m.default.default : m.default;
@@ -617,12 +1133,12 @@ class TheatreStudio {
617
1133
  });
618
1134
  });
619
1135
  }
620
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreStudio, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
621
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: TheatreStudio, isStandalone: true, selector: "theatre-project[studio]", inputs: { enabled: { classPropertyName: "enabled", publicName: "studio", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
1136
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreStudio, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1137
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreStudio, isStandalone: true, selector: "theatre-project[studio]", inputs: { enabled: { classPropertyName: "enabled", publicName: "studio", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
622
1138
  { provide: THEATRE_STUDIO, useFactory: (studio) => studio.studio, deps: [TheatreStudio] },
623
1139
  ], exportAs: ["studio"], ngImport: i0 }); }
624
1140
  }
625
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreStudio, decorators: [{
1141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreStudio, decorators: [{
626
1142
  type: Directive,
627
1143
  args: [{
628
1144
  selector: 'theatre-project[studio]',
@@ -631,7 +1147,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
631
1147
  { provide: THEATRE_STUDIO, useFactory: (studio) => studio.studio, deps: [TheatreStudio] },
632
1148
  ],
633
1149
  }]
634
- }], ctorParameters: () => [] });
1150
+ }], ctorParameters: () => [], propDecorators: { enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "studio", required: false }] }] } });
635
1151
 
636
1152
  const defaultOptions = {
637
1153
  rate: 1,
@@ -639,12 +1155,65 @@ const defaultOptions = {
639
1155
  autopause: false,
640
1156
  delay: 0,
641
1157
  };
1158
+ /**
1159
+ * Directive that provides control over a Theatre.js sequence.
1160
+ *
1161
+ * A sequence controls the playback of animations within a sheet. This directive
1162
+ * provides methods to play, pause, and reset the sequence, as well as reactive
1163
+ * signals for the current position, playing state, and length.
1164
+ *
1165
+ * Must be used on an element that also has the `sheet` directive.
1166
+ *
1167
+ * @example
1168
+ * ```html
1169
+ * <ng-container sheet="scene" [sequence]="{ autoplay: true, rate: 1 }" #seq="sequence">
1170
+ * <p>Position: {{ seq.position() }}</p>
1171
+ * <button (click)="seq.play()">Play</button>
1172
+ * <button (click)="seq.pause()">Pause</button>
1173
+ * </ng-container>
1174
+ * ```
1175
+ *
1176
+ * @example
1177
+ * ```html
1178
+ * <!-- With audio synchronization -->
1179
+ * <ng-container
1180
+ * sheet="scene"
1181
+ * [sequence]="{ autoplay: true }"
1182
+ * [sequenceAudio]="{ source: '/audio/soundtrack.mp3' }"
1183
+ * />
1184
+ * ```
1185
+ */
642
1186
  class TheatreSequence {
643
1187
  constructor() {
644
- this.options = input(defaultOptions, ...(ngDevMode ? [{ debugName: "options", alias: 'sequence', transform: mergeInputs(defaultOptions) }] : [{ alias: 'sequence', transform: mergeInputs(defaultOptions) }]));
645
- this.audioOptions = input(undefined, ...(ngDevMode ? [{ debugName: "audioOptions", alias: 'sequenceAudio' }] : [{ alias: 'sequenceAudio' }]));
1188
+ /**
1189
+ * Sequence configuration options.
1190
+ * Merged with default options using ngxtension's mergeInputs.
1191
+ *
1192
+ * @default { rate: 1, autoplay: false, autopause: false, delay: 0 }
1193
+ */
1194
+ this.options = input(defaultOptions, { ...(ngDevMode ? { debugName: "options" } : {}), alias: 'sequence', transform: mergeInputs(defaultOptions) });
1195
+ /**
1196
+ * Audio options for synchronizing playback with an audio file.
1197
+ * When provided, the sequence will be synchronized with the audio.
1198
+ */
1199
+ this.audioOptions = input(undefined, { ...(ngDevMode ? { debugName: "audioOptions" } : {}), alias: 'sequenceAudio' });
1200
+ /**
1201
+ * Two-way bindable signal for the current playback position in seconds.
1202
+ *
1203
+ * @default 0
1204
+ */
646
1205
  this.position = model(0, ...(ngDevMode ? [{ debugName: "position" }] : []));
1206
+ /**
1207
+ * Two-way bindable signal indicating whether the sequence is currently playing.
1208
+ *
1209
+ * @default false
1210
+ */
647
1211
  this.playing = model(false, ...(ngDevMode ? [{ debugName: "playing" }] : []));
1212
+ /**
1213
+ * Two-way bindable signal for the total length of the sequence in seconds.
1214
+ *
1215
+ * @default 0
1216
+ */
648
1217
  this.length = model(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
649
1218
  this.playOptions = omit(this.options, ['autoplay', 'autopause', 'delay', 'autoreset']);
650
1219
  this.autoplay = pick(this.options, 'autoplay');
@@ -653,6 +1222,9 @@ class TheatreSequence {
653
1222
  this.delay = pick(this.options, 'delay');
654
1223
  this.project = inject(TheatreProject);
655
1224
  this.sheet = inject(TheatreSheet$1, { host: true });
1225
+ /**
1226
+ * Computed signal containing the Theatre.js sequence instance.
1227
+ */
656
1228
  this.sequence = computed(() => this.sheet.sheet().sequence, ...(ngDevMode ? [{ debugName: "sequence" }] : []));
657
1229
  effect((onCleanup) => {
658
1230
  const autoplay = untracked(this.autoplay);
@@ -707,10 +1279,21 @@ class TheatreSequence {
707
1279
  });
708
1280
  });
709
1281
  }
1282
+ /**
1283
+ * Pauses the sequence playback at the current position.
1284
+ */
710
1285
  pause() {
711
1286
  const sequence = this.sequence();
712
1287
  sequence.pause();
713
1288
  }
1289
+ /**
1290
+ * Starts or resumes sequence playback.
1291
+ *
1292
+ * Waits for the project to be ready before starting playback.
1293
+ * Options are merged with the configured play options.
1294
+ *
1295
+ * @param options - Optional play options that override the configured options
1296
+ */
714
1297
  play(options = {}) {
715
1298
  const sequence = this.sequence();
716
1299
  const project = this.project.project();
@@ -718,6 +1301,12 @@ class TheatreSequence {
718
1301
  sequence.play({ ...this.playOptions(), ...options });
719
1302
  });
720
1303
  }
1304
+ /**
1305
+ * Resets the sequence position to 0.
1306
+ *
1307
+ * If the sequence was playing before reset, it will continue playing
1308
+ * from the beginning.
1309
+ */
721
1310
  reset() {
722
1311
  const sequence = this.sequence();
723
1312
  const isPlaying = val(sequence.pointer.playing);
@@ -725,14 +1314,36 @@ class TheatreSequence {
725
1314
  if (isPlaying)
726
1315
  this.play();
727
1316
  }
728
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSequence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
729
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: TheatreSequence, isStandalone: true, selector: "[sheet][sequence]", inputs: { options: { classPropertyName: "options", publicName: "sequence", isSignal: true, isRequired: false, transformFunction: null }, audioOptions: { classPropertyName: "audioOptions", publicName: "sequenceAudio", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, playing: { classPropertyName: "playing", publicName: "playing", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { position: "positionChange", playing: "playingChange", length: "lengthChange" }, exportAs: ["sequence"], ngImport: i0 }); }
1317
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSequence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1318
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSequence, isStandalone: true, selector: "[sheet][sequence]", inputs: { options: { classPropertyName: "options", publicName: "sequence", isSignal: true, isRequired: false, transformFunction: null }, audioOptions: { classPropertyName: "audioOptions", publicName: "sequenceAudio", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, playing: { classPropertyName: "playing", publicName: "playing", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { position: "positionChange", playing: "playingChange", length: "lengthChange" }, exportAs: ["sequence"], ngImport: i0 }); }
730
1319
  }
731
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TheatreSequence, decorators: [{
1320
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSequence, decorators: [{
732
1321
  type: Directive,
733
1322
  args: [{ selector: '[sheet][sequence]', exportAs: 'sequence' }]
734
- }], ctorParameters: () => [] });
1323
+ }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "sequence", required: false }] }], audioOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "sequenceAudio", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }, { type: i0.Output, args: ["positionChange"] }], playing: [{ type: i0.Input, args: [{ isSignal: true, alias: "playing", required: false }] }, { type: i0.Output, args: ["playingChange"] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }, { type: i0.Output, args: ["lengthChange"] }] } });
735
1324
 
1325
+ /**
1326
+ * Angular Three Theatre.js integration library
1327
+ *
1328
+ * This library provides Angular components and directives for integrating
1329
+ * Theatre.js animation toolkit with Angular Three applications.
1330
+ *
1331
+ * @packageDocumentation
1332
+ */
1333
+ /**
1334
+ * Combined array of TheatreSheet and TheatreSequence directives for convenient importing.
1335
+ *
1336
+ * @example
1337
+ * ```typescript
1338
+ * import { TheatreSheet } from 'angular-three-theatre';
1339
+ *
1340
+ * @Component({
1341
+ * imports: [TheatreSheet],
1342
+ * template: `<ng-container sheet="mySheet" sequence />`
1343
+ * })
1344
+ * export class MyComponent {}
1345
+ * ```
1346
+ */
736
1347
  const TheatreSheet = [TheatreSheet$1, TheatreSequence];
737
1348
 
738
1349
  /**