reacthub-pixitweenjs 0.3.0-alpha.3 → 0.3.0-alpha.4

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.
Files changed (139) hide show
  1. package/README.md +25 -16
  2. package/dist/components/AepComposition/AepAudioLayer.d.ts +6 -0
  3. package/dist/components/AepComposition/AepComposition.d.ts +2 -0
  4. package/dist/components/AepComposition/AudioPlaybackManager.d.ts +38 -0
  5. package/dist/components/AepComposition/index.d.ts +3 -0
  6. package/dist/components/AepComposition/model3d/Pixi3DModelLayer.d.ts +9 -0
  7. package/dist/components/AepComposition/model3d/ThreeOffscreenRenderer.d.ts +49 -0
  8. package/dist/components/AepComposition/model3d/framing.d.ts +30 -0
  9. package/dist/components/AepComposition/model3d/geometry.d.ts +27 -0
  10. package/dist/components/AepComposition/model3d/index.d.ts +14 -0
  11. package/dist/components/AepComposition/model3d/lighting.d.ts +40 -0
  12. package/dist/components/AepComposition/model3d/readiness.d.ts +17 -0
  13. package/dist/components/AepComposition/model3d/sampleModel3D.d.ts +40 -0
  14. package/dist/components/PixiAudioSprite/HowlerAudioSprite.d.ts +8 -2
  15. package/dist/components/PixiAudioSprite/PixiAudioSprite.d.ts +37 -1
  16. package/dist/components/PixiAudioSprite/index.d.ts +3 -0
  17. package/dist/components/PixiAudioSprite/useAudioVisualizer.d.ts +30 -15
  18. package/dist/components/PixiCaptionsTrack/PixiCaptionsTrack.d.ts +86 -0
  19. package/dist/components/PixiCaptionsTrack/index.d.ts +5 -0
  20. package/dist/components/PixiCaptionsTrack/useCaptionPlayhead.d.ts +31 -0
  21. package/dist/components/PixiCaptionsTrack/useCaptionStyles.d.ts +45 -0
  22. package/dist/components/PixiCaptionsTrack/useEmojiTextures.d.ts +8 -0
  23. package/dist/components/PixiImageSprite/PixiImageSprite.d.ts +17 -0
  24. package/dist/components/PixiSVGSprite/PixiSvgImageSprite.d.ts +35 -0
  25. package/dist/components/PixiSVGSprite/PixiSvgPathSprite.d.ts +10 -0
  26. package/dist/components/PixiSVGSprite/PixiSvgRawSprite.d.ts +30 -0
  27. package/dist/components/PixiSVGSprite/index.d.ts +4 -0
  28. package/dist/components/PixiSequence/PixiSequence.d.ts +29 -5
  29. package/dist/components/PixiTextSprite/PixiTextSplit.d.ts +1 -1
  30. package/dist/components/PixiTextSprite/PixiTextSprite.d.ts +25 -0
  31. package/dist/components/PixiThreeSprite/PixiThreeModelSprite.d.ts +23 -0
  32. package/dist/components/PixiThreeSprite/index.d.ts +2 -0
  33. package/dist/components/PixiVideoSprite/PixiVideoSprite.d.ts +26 -0
  34. package/dist/components/index.d.ts +2 -0
  35. package/dist/constants/animation.d.ts +232 -0
  36. package/dist/constants/animationConstants.d.ts +90 -0
  37. package/dist/constants/elementNames.d.ts +4 -0
  38. package/dist/filters/animated-vfx/AnimatedVfxFilter.d.ts +19 -0
  39. package/dist/filters/animated-vfx/composeShader.d.ts +2 -0
  40. package/dist/filters/animated-vfx/index.d.ts +14 -0
  41. package/dist/filters/animated-vfx/registry/animatedVfxRegistry.d.ts +65 -0
  42. package/dist/filters/animated-vfx/registry/waveTearVariants.d.ts +14 -0
  43. package/dist/filters/animated-vfx/toStrength.d.ts +1 -0
  44. package/dist/filters/animated-vfx/types.d.ts +18 -0
  45. package/dist/filters/animatedVfxFilters.d.ts +1 -0
  46. package/dist/filters/blend-mode/createBlendCompositeFilter.d.ts +26 -0
  47. package/dist/filters/edge-feather/EdgeFeatherFilter.d.ts +19 -0
  48. package/dist/filters/plate-key/PlateKeyFilter.d.ts +29 -0
  49. package/dist/hocs/AbstractContainer.d.ts +5 -0
  50. package/dist/hocs/BorderMaskContainer.d.ts +23 -8
  51. package/dist/hocs/drawMaskShape.d.ts +6 -2
  52. package/dist/hooks/index.d.ts +10 -0
  53. package/dist/hooks/useBlendFilter.d.ts +17 -0
  54. package/dist/hooks/useDebouncedValue.d.ts +11 -0
  55. package/dist/hooks/useFontEpoch.d.ts +10 -0
  56. package/dist/hooks/usePixiAnimation.d.ts +24 -0
  57. package/dist/hooks/useSpriteFilters.d.ts +54 -12
  58. package/dist/hooks/useSvgTexture.d.ts +29 -0
  59. package/dist/hooks/video/useVideoLifecycle.d.ts +23 -0
  60. package/dist/hooks/video/useVideoTexture.d.ts +34 -0
  61. package/dist/hooks/video/useVideoTimelineSync.d.ts +24 -0
  62. package/dist/hooks/withEffectsHook.d.ts +326 -0
  63. package/dist/hooks/withFiltersHook.d.ts +104 -38
  64. package/dist/index.es.js +47089 -30995
  65. package/dist/index.umd.js +1616 -194
  66. package/dist/providers/GsapPixieContextProvider.d.ts +7 -0
  67. package/dist/types/BaseProps.d.ts +41 -14
  68. package/dist/types/CropTypes.d.ts +12 -0
  69. package/dist/types/Effects.d.ts +674 -13
  70. package/dist/types/aep/asset.d.ts +7 -7
  71. package/dist/types/aep/camera.d.ts +64 -64
  72. package/dist/types/aep/composition.d.ts +1 -1
  73. package/dist/types/aep/effect.d.ts +2 -2
  74. package/dist/types/aep/layer.d.ts +11733 -6766
  75. package/dist/types/aep/light.d.ts +80 -80
  76. package/dist/types/aep/postFx.d.ts +2 -2
  77. package/dist/types/aep/text-animator.d.ts +6 -6
  78. package/dist/types/aep/transform.d.ts +14 -14
  79. package/dist/types/aep/transform3D.d.ts +18 -18
  80. package/dist/types/index.d.ts +1 -0
  81. package/dist/utils/PixiSelector.d.ts +17 -0
  82. package/dist/utils/assetRefCount.d.ts +20 -0
  83. package/dist/utils/audio/audioRegistry.d.ts +51 -0
  84. package/dist/utils/audio/audioSync.d.ts +98 -0
  85. package/dist/utils/audio/gainEnvelope.d.ts +162 -0
  86. package/dist/utils/audio/useAudioRegistry.d.ts +10 -0
  87. package/dist/utils/blendMode.d.ts +21 -0
  88. package/dist/utils/captions/captionClock.d.ts +17 -0
  89. package/dist/utils/captions/captionDisplay.d.ts +57 -0
  90. package/dist/utils/captions/captionPose.d.ts +107 -0
  91. package/dist/utils/captions/captionVisual.d.ts +32 -0
  92. package/dist/utils/captions/captionWordLayout.d.ts +67 -0
  93. package/dist/utils/captions/groupSegments.d.ts +20 -0
  94. package/dist/utils/captions/index.d.ts +10 -0
  95. package/dist/utils/captions/parseSubtitles.d.ts +25 -0
  96. package/dist/utils/captions/sampleCaption.d.ts +25 -0
  97. package/dist/utils/captions/timeBase.d.ts +34 -0
  98. package/dist/utils/captions/types.d.ts +279 -0
  99. package/dist/utils/entranceOverlap.d.ts +37 -0
  100. package/dist/utils/fonts/fontLoader.d.ts +33 -0
  101. package/dist/utils/fonts/fontSpec.d.ts +16 -0
  102. package/dist/utils/fonts/googleFonts.d.ts +9 -0
  103. package/dist/utils/gifTiming.d.ts +22 -0
  104. package/dist/utils/gsapEffects/animationConfigs.d.ts +3802 -0
  105. package/dist/utils/gsapEffects/backEffects.d.ts +1 -0
  106. package/dist/utils/gsapEffects/bounceEffects.d.ts +1 -0
  107. package/dist/utils/gsapEffects/effectGenerator.d.ts +3 -0
  108. package/dist/utils/gsapEffects/effectTarget.d.ts +11 -0
  109. package/dist/utils/gsapEffects/fadeEffects.d.ts +1 -0
  110. package/dist/utils/gsapEffects/flipEffects.d.ts +1 -0
  111. package/dist/utils/gsapEffects/generalEffects.d.ts +1 -0
  112. package/dist/utils/gsapEffects/index.d.ts +0 -0
  113. package/dist/utils/gsapEffects/lightSpeedEffect.d.ts +1 -0
  114. package/dist/utils/gsapEffects/logoRevealEffects.d.ts +1 -0
  115. package/dist/utils/gsapEffects/registerEffects.d.ts +1 -0
  116. package/dist/utils/gsapEffects/riseEffect.d.ts +1 -0
  117. package/dist/utils/gsapEffects/rollEffects.d.ts +1 -0
  118. package/dist/utils/gsapEffects/rotateEffects.d.ts +1 -0
  119. package/dist/utils/gsapEffects/slideEffects.d.ts +1 -0
  120. package/dist/utils/gsapEffects/staggerTextEffects.d.ts +1 -0
  121. package/dist/utils/gsapEffects/textUnitEffects.d.ts +1 -0
  122. package/dist/utils/gsapEffects/textUnitMask.d.ts +1 -0
  123. package/dist/utils/gsapEffects/textUnits.d.ts +172 -0
  124. package/dist/utils/gsapEffects/typewriterEffect.d.ts +1 -0
  125. package/dist/utils/gsapEffects/wipeEffect.d.ts +1 -0
  126. package/dist/utils/gsapEffects/zoomEffects.d.ts +1 -0
  127. package/dist/utils/index.d.ts +25 -0
  128. package/dist/utils/loadSpriteTexture.d.ts +33 -4
  129. package/dist/utils/sanitizeCanvasText.d.ts +12 -0
  130. package/dist/utils/sanitizeImageSrc.d.ts +7 -0
  131. package/dist/utils/svgRaster.d.ts +47 -0
  132. package/dist/utils/textLayout/index.d.ts +1 -1
  133. package/dist/utils/textLayout/layoutText.d.ts +5 -0
  134. package/dist/utils/textStyle.d.ts +81 -0
  135. package/dist/utils/textStyleV8.d.ts +62 -0
  136. package/dist/utils/threeModel.d.ts +55 -0
  137. package/dist/utils/videoAssetCache.d.ts +4 -0
  138. package/dist/utils/videoReadiness.d.ts +13 -0
  139. package/package.json +3 -8
package/README.md CHANGED
@@ -193,9 +193,9 @@ Display images with advanced transformations and filters.
193
193
  alpha: 1,
194
194
  scale: 1,
195
195
  colorCorrection: {
196
- temperature: 6500,
197
- contrast: 1,
198
- saturation: 1,
196
+ temperature: 10, // slider units: -100..100, 0 = no change
197
+ contrast: 0,
198
+ saturation: 0,
199
199
  blurRadius: 0,
200
200
  },
201
201
  }}
@@ -385,27 +385,36 @@ Create complex animations with precise timing:
385
385
  ### 🎨 Color Correction & Effects
386
386
 
387
387
  Driven by the shared `useSpriteFilters` hook (Pixi v8 + `pixi-filters` v6).
388
- Ordered filter chain: temperature → sharpness → HSL → adjustment →
389
- effect preset → blur → vignette → noise.
388
+ Ordered filter chain: plateKey → exposure → temperature/tint → highlights/shadows →
389
+ adjustment → vibrance → hue → sharpness → edge feather → effect preset → blur → vignette →
390
+ noise → blend composite.
391
+
392
+ `colorCorrection` uses **slider units** (neutral = `0`), the same as the Clippy editor:
390
393
 
391
394
  ```tsx
392
395
  transformation={{
393
396
  colorCorrection: {
394
- temperature: 10, // -100 to +100 (warm/cool)
395
- contrast: 1.2,
396
- saturation: 1.5,
397
- brightness: 1.1,
398
- hue: 0, // degrees
399
- sharpness: 0.3, // 0–1
400
- blurRadius: 0, // Kawasaki blur strength
401
- vignette: 0, // 0–1
402
- noise: 0, // 0–1
403
- red: 1, green: 1, blue: 1, alpha: 1, gamma: 1,
397
+ // -100..100, 0 = no change
398
+ brightness: 0, contrast: 20, saturation: 40,
399
+ red: 0, green: 0, blue: 0,
400
+ temperature: 10, tint: 0,
401
+ highlights: 0, shadows: 0, exposure: 0, vibrance: 0,
402
+ hue: 0, // -180..180 degrees
403
+ // 0..100
404
+ sharpness: 0, blurRadius: 0, vignette: 0, noise: 0, edgeFeather: 0,
405
+ // 1 = no change
406
+ gamma: 1, alpha: 1,
404
407
  },
405
- effect: "Sepia", // BlackAndWhite | Sepia | RetroVintage | NightVision | CYAN | Vignette | None
408
+ // Legacy string, or { name, intensity (0-100), params } for the ~60 presets
409
+ // (Warm, Cool, Cinematic, Neon, VHS, GlitchWave, ...). See Effects.
410
+ effects: { name: "Sepia", intensity: 100 },
411
+ blendMode: 4, // numeric code; 4 = overlay (see BlendModes)
406
412
  }}
407
413
  ```
408
414
 
415
+ Migrating from the old multiplier convention (`contrast: 1.2` = +20%)? Use
416
+ `fromMultiplierColorCorrection({ contrast: 1.2 })` → `{ contrast: 20 }`.
417
+
409
418
  ### 🪟 Border + Mask
410
419
 
411
420
  Every uplifted sprite supports an optional border stroke and a mask
@@ -10,6 +10,10 @@ export interface AepAudioLayerProps {
10
10
  pan?: AepAnimatable<number>;
11
11
  muted?: boolean;
12
12
  visible?: boolean;
13
+ /** Offset into the audio FILE the clip starts from, seconds. Default 0. */
14
+ trimStart?: number;
15
+ /** Playback rate. Default 1. */
16
+ speed?: number;
13
17
  transformation: {
14
18
  x: number;
15
19
  y: number;
@@ -25,4 +29,6 @@ export interface AepAudioLayerProps {
25
29
  };
26
30
  onContainerRefReady?: (uniqueId: string, ref: React.MutableRefObject<unknown>) => void;
27
31
  }
32
+ /** Layer frame at master time `t`: keyframe `t === inPoint` sits at `offsetSec`. */
33
+ export declare const layerFrameAt: (t: number, offsetSec: number, inPointFrames: number, fps: number) => number;
28
34
  export declare const AepAudioLayer: React.FC<AepAudioLayerProps>;
@@ -12,5 +12,7 @@ export interface AepCompositionProps {
12
12
  onError?: (err: unknown) => void;
13
13
  theme?: AepThemeMap;
14
14
  textOverrides?: AepTextOverrideMap;
15
+ onRenderReady?: () => void;
16
+ onLayerError?: (layerId: string, error: unknown) => void;
15
17
  }
16
18
  export declare const AepComposition: React.FC<AepCompositionProps>;
@@ -0,0 +1,38 @@
1
+ import { AudioRegistry } from '../../utils/audio/audioRegistry';
2
+ import { AudioClipSpec } from '../../utils/audio/audioSync';
3
+ import * as React from "react";
4
+ export type AudioPlaybackElement = AudioClipSpec;
5
+ export interface AudioPlaybackManagerProps {
6
+ audioElements: ReadonlyArray<AudioPlaybackElement>;
7
+ /** Defaults to the shared registry. Pass your own to isolate multiple players. */
8
+ registry?: AudioRegistry;
9
+ /**
10
+ * Stop and release EVERY element in the registry (and close its audio context) when this
11
+ * unmounts. Default true: right for the one editor-wide manager that owns the registry. Turn it
12
+ * off when the registry is shared with others and you only want to remove your own clips.
13
+ */
14
+ clearOnUnmount?: boolean;
15
+ }
16
+ /**
17
+ * AudioPlaybackManager — the single owner of audio playback. Renders nothing; mount it once,
18
+ * anywhere under the GSAP provider (it does not need to be inside the Pixi stage).
19
+ *
20
+ * Ported from the Clippy editor. The architecture is the point: ONE listener on the master
21
+ * timeline decides, for every clip, whether its element should be playing, where, and how loud.
22
+ * It replaces the old per-sprite GSAP tweens whose onStart/onUpdate hooks raced when clips were
23
+ * added dynamically, and it has no per-clip timing state to go stale.
24
+ *
25
+ * The decision itself is pure (`decideAudioSync`) and unit-tested; this component only owns the
26
+ * element lifecycle and the event wiring. Differences from Clippy:
27
+ * - plain `HTMLAudioElement` instead of Howler (no dependency; same streaming behaviour as
28
+ * Howler's html5 mode, which Clippy already uses)
29
+ * - the playhead moving BACKWARDS or being scrubbed pauses the clips (Clippy kept playing
30
+ * forward and re-seeked every 200 ms)
31
+ * - the file position honours `speed` (Clippy's drifted at any speed other than 1)
32
+ * - handles `play()` being blocked by the autoplay policy, and element load errors, instead of
33
+ * silently stalling
34
+ * - a RESUME event starts clips immediately rather than waiting for the next tick
35
+ */
36
+ declare const AudioPlaybackManager: React.FC<AudioPlaybackManagerProps>;
37
+ export default AudioPlaybackManager;
38
+ export { AudioPlaybackManager };
@@ -37,3 +37,6 @@ export { AepTextOverrideProvider, useAepTextOverride, resolveTextSource, } from
37
37
  export type { AepTextOverrideMap } from './AepTextOverrideContext';
38
38
  export { resolvePostFxList } from './resolvePostFxList';
39
39
  export { shouldSplitText } from './shouldSplitText';
40
+ export { AudioPlaybackManager } from './AudioPlaybackManager';
41
+ export type { AudioPlaybackManagerProps, AudioPlaybackElement, } from './AudioPlaybackManager';
42
+ export * from './model3d';
@@ -0,0 +1,9 @@
1
+ import { ForwardedRefResponse, PixiBaseSpriteProps } from '../../../types/BaseProps';
2
+ import { AepModel3DLayer } from '../../../types/aep';
3
+ import * as React from "react";
4
+ export interface Pixi3DModelLayerProps extends PixiBaseSpriteProps {
5
+ layer: AepModel3DLayer;
6
+ }
7
+ export declare const Pixi3DModelLayer: React.MemoExoticComponent<({ ref, layer, ...props }: Pixi3DModelLayerProps & {
8
+ ref?: React.Ref<ForwardedRefResponse | null>;
9
+ }) => import("react/jsx-runtime").JSX.Element>;
@@ -0,0 +1,49 @@
1
+ import * as THREE from "three";
2
+ export interface OffscreenRenderRequest {
3
+ canvas: HTMLCanvasElement;
4
+ scene: THREE.Scene;
5
+ camera: THREE.PerspectiveCamera;
6
+ width: number;
7
+ height: number;
8
+ }
9
+ /** The slice of THREE.WebGLRenderer this service uses (lets tests inject a fake). */
10
+ export interface OffscreenGlRenderer {
11
+ readonly domElement: HTMLCanvasElement;
12
+ setSize(width: number, height: number, updateStyle?: boolean): void;
13
+ setViewport(x: number, y: number, width: number, height: number): void;
14
+ render(scene: THREE.Scene, camera: THREE.Camera): void;
15
+ dispose(): void;
16
+ forceContextLoss(): void;
17
+ }
18
+ export declare class ThreeOffscreenRenderer {
19
+ readonly renderer: THREE.WebGLRenderer;
20
+ private readonly gl;
21
+ private width;
22
+ private height;
23
+ constructor(gl?: OffscreenGlRenderer);
24
+ render({ canvas, scene, camera, width, height }: OffscreenRenderRequest): void;
25
+ dispose(): void;
26
+ }
27
+ /**
28
+ * Reference-counted pool of shared things keyed by owner (a Pixi `Application`).
29
+ *
30
+ * The last release schedules disposal after a grace period, so a StrictMode double-mount or a
31
+ * stage remount reuses the same renderer instead of tearing down and recreating a WebGL context.
32
+ * Without this, every Application (each Storybook story switch, for example) leaked a context
33
+ * until the browser's ~16 context cap started dropping live ones.
34
+ */
35
+ export declare function createRendererPool<T extends {
36
+ dispose(): void;
37
+ }>(create: () => T, graceMs?: number): {
38
+ acquire(owner: unknown): T;
39
+ release(owner: unknown): void;
40
+ size: () => number;
41
+ };
42
+ /**
43
+ * Take a use of the shared renderer for a Pixi `Application` (or a process-wide fallback when no
44
+ * application is available, e.g. in tests/portals). Pair every call with `releaseOffscreenRenderer`.
45
+ */
46
+ export declare function acquireOffscreenRenderer(app?: object | null): ThreeOffscreenRenderer;
47
+ export declare function releaseOffscreenRenderer(app?: object | null): void;
48
+ /** @deprecated Does not track ownership; use `acquireOffscreenRenderer` / `releaseOffscreenRenderer`. */
49
+ export declare function getOffscreenRenderer(app?: object | null): ThreeOffscreenRenderer;
@@ -0,0 +1,30 @@
1
+ export interface CameraFraming {
2
+ position: [number, number, number];
3
+ target: [number, number, number];
4
+ }
5
+ /**
6
+ * Fixed camera for a model whose rest-pose bounds are `center` / `maxDim`.
7
+ *
8
+ * The camera frames the UNSCALED, UNTRANSLATED model and never follows it. Following `view.position`
9
+ * or compensating for `view.scale` would cancel the very motion those keyframes describe (the
10
+ * object would sit still in the viewport). Use `camera.fit` to leave room for growth or travel.
11
+ */
12
+ export declare function frameCamera(center: readonly [number, number, number], maxDim: number, fovDeg: number, fit: number): CameraFraming;
13
+ /** Seconds into a glTF clip: relative to the layer's in-point, never negative. */
14
+ export declare function clipTimeSeconds(frame: number, inPointFrames: number, fps: number): number;
15
+ /** Whether `frame` is inside the layer's half-open window [inPoint, outPoint). */
16
+ export declare function isFrameInRange(frame: number, inPointFrames: number, outPointFrames: number): boolean;
17
+ export interface FramingBounds {
18
+ center: [number, number, number];
19
+ /** Largest edge, in model units. */
20
+ maxDim: number;
21
+ }
22
+ /**
23
+ * Bounds used to frame the camera. An authored `bounds` override wins over what was measured from
24
+ * the loaded model; its `center` defaults to the measured centre. Measured bounds of a skinned
25
+ * glTF are cached at the first pose and do not follow the animation, hence the override.
26
+ */
27
+ export declare function resolveFramingBounds(measured: FramingBounds, override?: {
28
+ center?: readonly [number, number, number];
29
+ size: readonly [number, number, number];
30
+ }): FramingBounds;
@@ -0,0 +1,27 @@
1
+ import { AepModel3DSource } from '../../../types/aep';
2
+ import * as THREE from "three";
3
+ export type PrimitiveShape = Extract<AepModel3DSource, {
4
+ type: "primitive";
5
+ }>["shape"];
6
+ export interface PrimitiveProportions {
7
+ width?: number;
8
+ height?: number;
9
+ depth?: number;
10
+ }
11
+ export declare function buildPrimitiveGeometry(shape: PrimitiveShape, proportions?: PrimitiveProportions): THREE.BufferGeometry;
12
+ export interface ExtrudeGeometryResult {
13
+ geometry: THREE.ExtrudeGeometry;
14
+ /** Contour width/height in the same units as the input points. */
15
+ width: number;
16
+ height: number;
17
+ }
18
+ export declare function buildExtrudeGeometry(contour: ReadonlyArray<readonly [number, number]>, depth: number, bevel?: number): ExtrudeGeometryResult;
19
+ export interface BuiltSourceGeometry {
20
+ geometry: THREE.BufferGeometry;
21
+ /**
22
+ * True when the geometry has two material groups: caps (0) and sides (1).
23
+ * Boxes have six groups (+X, -X, +Y, -Y, +Z, -Z).
24
+ */
25
+ materialGroups: "single" | "extrude" | "box";
26
+ }
27
+ export declare function buildSourceGeometry(source: AepModel3DSource, sampledDepth: number): BuiltSourceGeometry;
@@ -0,0 +1,14 @@
1
+ export { Pixi3DModelLayer } from './Pixi3DModelLayer';
2
+ export type { Pixi3DModelLayerProps } from './Pixi3DModelLayer';
3
+ export { AepReadinessProvider, useAepCompositionReady, useAepReadiness, } from './readiness';
4
+ export type { AepReadinessContextValue } from './readiness';
5
+ export { ThreeOffscreenRenderer, acquireOffscreenRenderer, releaseOffscreenRenderer, createRendererPool, getOffscreenRenderer, } from './ThreeOffscreenRenderer';
6
+ export type { OffscreenRenderRequest, OffscreenGlRenderer, } from './ThreeOffscreenRenderer';
7
+ export { frameCamera, clipTimeSeconds, isFrameInRange } from './framing';
8
+ export type { CameraFraming } from './framing';
9
+ export { LIGHTING_PRESETS, DEFAULT_LIGHTING_PRESET, resolveLightingConfig, directionFromAzimuthElevation, } from './lighting';
10
+ export type { LightingConfig, LightingOverrides, LightingPresetName, LightingRig, } from './lighting';
11
+ export { buildPrimitiveGeometry, buildExtrudeGeometry, buildSourceGeometry, } from './geometry';
12
+ export type { PrimitiveShape, PrimitiveProportions, ExtrudeGeometryResult, BuiltSourceGeometry, } from './geometry';
13
+ export { sampleModel3DState, model3DStateKey, MODEL3D_DEFAULTS, } from './sampleModel3D';
14
+ export type { SampledModel3DState } from './sampleModel3D';
@@ -0,0 +1,40 @@
1
+ import { AepModel3DLighting } from '../../../types/aep';
2
+ import * as THREE from "three";
3
+ export type LightingPresetName = NonNullable<AepModel3DLighting["preset"]>;
4
+ export interface LightingConfig {
5
+ preset: LightingPresetName;
6
+ keyAzimuth: number;
7
+ keyElevation: number;
8
+ keyIntensity: number;
9
+ keyColor: string;
10
+ fillIntensity: number;
11
+ rimIntensity: number;
12
+ ambientIntensity: number;
13
+ environmentIntensity: number;
14
+ environment: "room" | "none";
15
+ }
16
+ export declare const LIGHTING_PRESETS: Record<LightingPresetName, LightingConfig>;
17
+ export declare const DEFAULT_LIGHTING_PRESET: LightingPresetName;
18
+ export interface LightingOverrides {
19
+ keyAzimuth?: number;
20
+ keyElevation?: number;
21
+ keyIntensity?: number;
22
+ keyColor?: string;
23
+ fillIntensity?: number;
24
+ rimIntensity?: number;
25
+ }
26
+ export declare function resolveLightingConfig(presetName?: LightingPresetName, overrides?: LightingOverrides, environment?: AepModel3DLighting["environment"]): LightingConfig;
27
+ /** Unit vector pointing from the light's target toward the light. */
28
+ export declare function directionFromAzimuthElevation(azimuthDeg: number, elevationDeg: number): [number, number, number];
29
+ export interface LightingRig {
30
+ group: THREE.Group;
31
+ ambient: THREE.AmbientLight;
32
+ key: THREE.DirectionalLight;
33
+ fill: THREE.DirectionalLight;
34
+ rim: THREE.DirectionalLight;
35
+ }
36
+ export declare function createLightingRig(config: LightingConfig): LightingRig;
37
+ export declare function applyLightingRig(rig: LightingRig, config: LightingConfig): void;
38
+ export declare function disposeLightingRig(rig: LightingRig): void;
39
+ export declare function getRoomEnvironmentTexture(renderer: THREE.WebGLRenderer): THREE.Texture;
40
+ export declare function applyEnvironment(scene: THREE.Scene, config: LightingConfig, renderer: THREE.WebGLRenderer): void;
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+ export interface AepReadinessContextValue {
3
+ ready: boolean;
4
+ readyCount: number;
5
+ total: number;
6
+ register: (id: string) => () => void;
7
+ markReady: (id: string) => void;
8
+ reset: (id: string) => void;
9
+ reportError: (id: string, error: unknown) => void;
10
+ }
11
+ export declare function useAepCompositionReady(): boolean;
12
+ export declare function useAepReadiness(): AepReadinessContextValue;
13
+ export interface AepReadinessProviderProps {
14
+ children: React.ReactNode;
15
+ onLayerError?: (layerId: string, error: unknown) => void;
16
+ }
17
+ export declare const AepReadinessProvider: React.FC<AepReadinessProviderProps>;
@@ -0,0 +1,40 @@
1
+ import { AepModel3DLayer } from '../../../types/aep';
2
+ import { LightingPresetName } from './lighting';
3
+ export interface SampledModel3DState {
4
+ rotation: [number, number, number];
5
+ position: [number, number, number];
6
+ scale: number;
7
+ extrudeDepth: number;
8
+ roughness: number;
9
+ metalness: number;
10
+ clearcoat: number;
11
+ preset: LightingPresetName;
12
+ keyAzimuth: number;
13
+ keyElevation: number;
14
+ keyIntensity: number;
15
+ keyColor: string;
16
+ fillIntensity: number;
17
+ rimIntensity: number;
18
+ environment: "room" | "none";
19
+ shadowOpacity: number;
20
+ shadowSoftness: number;
21
+ shadowOffsetY: number;
22
+ fov: number;
23
+ fit: number;
24
+ }
25
+ export declare const MODEL3D_DEFAULTS: {
26
+ readonly rotation: [number, number, number];
27
+ readonly position: [number, number, number];
28
+ readonly scale: 1;
29
+ readonly roughness: 0.35;
30
+ readonly metalness: 0.05;
31
+ readonly clearcoat: 0;
32
+ readonly shadowOpacity: 0.35;
33
+ readonly shadowSoftness: 0.6;
34
+ readonly shadowOffsetY: 0;
35
+ readonly fov: 35;
36
+ readonly fit: 1.35;
37
+ };
38
+ export declare function sampleModel3DState(layer: AepModel3DLayer, frame: number): SampledModel3DState;
39
+ /** Deterministic identity for the sampled state, used for dirty checks. */
40
+ export declare function model3DStateKey(state: SampledModel3DState): string;
@@ -14,5 +14,11 @@ interface IAudioPlayer {
14
14
  playFromTime: (time: number) => void;
15
15
  }
16
16
  type UseAudioPlayer = (props: AudioPlayerProps) => IAudioPlayer;
17
- declare const useHowlerAudioPlayer: UseAudioPlayer;
18
- export default useHowlerAudioPlayer;
17
+ declare const useAudioElementPlayer: UseAudioPlayer;
18
+ /**
19
+ * Plain-`HTMLAudioElement` player hook (no Howler involved; the old name was a leftover).
20
+ * `useHowlerAudioPlayer` stays exported as an alias so existing imports keep working.
21
+ */
22
+ export { useAudioElementPlayer };
23
+ export declare const useHowlerAudioPlayer: UseAudioPlayer;
24
+ export default useAudioElementPlayer;
@@ -1,4 +1,6 @@
1
1
  import { PixiBaseSpriteProps, ForwardedRefResponse } from '../../types/BaseProps';
2
+ import { AudioFade, DuckWindow } from '../../utils/audio/gainEnvelope';
3
+ import { AudioRegistry } from '../../utils/audio/audioRegistry';
2
4
  import * as React from "react";
3
5
  import * as PIXI from "pixi.js";
4
6
  export interface PixiAudioSpriteProps extends PixiBaseSpriteProps {
@@ -6,15 +8,49 @@ export interface PixiAudioSpriteProps extends PixiBaseSpriteProps {
6
8
  src: string;
7
9
  startAt: number;
8
10
  endAt: number;
11
+ /** Offset into the audio FILE the clip starts from (seconds). */
9
12
  audioStartAt: number;
10
- audioEndAt: number;
13
+ /** @deprecated Unused. The clip length on the timeline is `endAt - startAt`. */
14
+ audioEndAt?: number;
11
15
  mute: boolean;
12
16
  speed: number;
13
17
  visible: boolean;
18
+ /** 0..1. Default 1. */
19
+ volume?: number;
20
+ /**
21
+ * Volume as a function of timeline time in seconds (wins over `volume`). Lets an animation
22
+ * drive the base volume while fades / ducking / mute still apply on top.
23
+ */
24
+ getVolume?: (timelineTime: number) => number;
25
+ audioFade?: AudioFade;
26
+ duckWindows?: DuckWindow[];
27
+ duckTo?: number;
28
+ /**
29
+ * Mount a private AudioPlaybackManager for this one clip (default true), so the sprite works
30
+ * standalone. Set false when the app mounts ONE manager for the whole timeline and passes all
31
+ * clips to it.
32
+ */
33
+ managePlayback?: boolean;
34
+ /** Registry to use instead of the shared default (isolates multiple players). */
35
+ registry?: AudioRegistry;
14
36
  onContainerRefReady?: (uniqueId: string, ref: React.MutableRefObject<PIXI.Container | null>) => void;
15
37
  onSpriteRefReady?: (uniqueId: string, ref: React.MutableRefObject<PIXI.Container | null>) => void;
38
+ /** Fires once the clip's <audio> element exists (and again if it is replaced). */
16
39
  onAudioElementReady?: (uniqueId: string, el: HTMLAudioElement) => void;
17
40
  }
41
+ /**
42
+ * PixiAudioSprite — an audio clip on the timeline, with an optional spectrum visualization.
43
+ *
44
+ * Playback is owned by `AudioPlaybackManager` (Clippy's architecture: one listener on the master
45
+ * timeline decides what plays, where and how loud). This component:
46
+ * 1. feeds its clip to a manager (its own by default; `managePlayback={false}` to opt out),
47
+ * 2. exposes the clip's `<audio>` element to callers via `onAudioElementReady`,
48
+ * 3. draws the waveform from that same element when `transformation.waveform` is set.
49
+ *
50
+ * Replaces the previous per-sprite GSAP tween driving a private `Audio`, whose onStart/onUpdate
51
+ * hooks raced when sprites were added dynamically, had no drift correction, ignored volume and
52
+ * fades, and re-created the element whenever any prop changed.
53
+ */
18
54
  declare const PixiAudioSprite: ({ ref, ...props }: PixiAudioSpriteProps & {
19
55
  ref?: React.Ref<ForwardedRefResponse | null>;
20
56
  }) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1,4 @@
1
1
  export { default as PixiAudioSprite } from './PixiAudioSprite';
2
+ export type { PixiAudioSpriteProps } from './PixiAudioSprite';
3
+ export { default as useAudioElementPlayer, useHowlerAudioPlayer, } from './HowlerAudioSprite';
4
+ export { default as useAudioVisualizer } from './useAudioVisualizer';
@@ -1,18 +1,33 @@
1
1
  import { default as AudioMotionAnalyzer } from 'audiomotion-analyzer';
2
- import { PixiBaseSpriteProps } from '../../types/BaseProps';
3
- import * as React from "react";
4
- export type AudioVisualizerProps = Partial<PixiBaseSpriteProps> & {
2
+ import { Waveforms } from '../../types/Effects';
3
+ import { AudioRegistry } from '../../utils/audio/audioRegistry';
4
+ export interface UseAudioVisualizerOptions {
5
5
  uniqueId: string;
6
- src: string;
7
- muted?: boolean;
8
- volume?: number;
9
- loop?: boolean;
10
- playbackRate?: number;
11
- visible?: boolean;
12
- };
13
- declare const useAudioVisualizer: (audioProps: AudioVisualizerProps) => {
14
- audioMotionRef: React.RefObject<AudioMotionAnalyzer | undefined>;
15
- blobUrl: string;
16
- canvasRef: React.RefObject<HTMLDivElement | null>;
17
- };
6
+ waveform: Waveforms;
7
+ width: number;
8
+ height: number;
9
+ /** Defaults to the shared registry the AudioPlaybackManager writes to. */
10
+ registry?: AudioRegistry;
11
+ }
12
+ export interface AudioVisualizer {
13
+ /** The analyzer canvas, once an element exists to tap. Wrap it in a Pixi CanvasSource. */
14
+ canvas: HTMLCanvasElement | null;
15
+ analyzer: AudioMotionAnalyzer | null;
16
+ }
17
+ /**
18
+ * Audio spectrum visualization for a clip, driven by the SAME `<audio>` element the
19
+ * AudioPlaybackManager plays.
20
+ *
21
+ * What changed from the previous version (and why):
22
+ * - it no longer `fetch`es the whole audio file into a blob just to build an element; it taps
23
+ * the element the manager already owns, so there is one download and one playback path
24
+ * - the element is routed through Web Audio ONCE, via the registry's shared source node, so a
25
+ * visualizer and stereo pan can coexist (previously they were mutually exclusive: a second
26
+ * `createMediaElementSource` throws)
27
+ * - the analyzer shares the registry's audio context; the manager resumes it on play
28
+ * - the analyzer is built once per (clip, size). A waveform change updates its options in place,
29
+ * because rebinding a new source node to the element is rejected by the browser
30
+ * - the analyzer and its host element are destroyed on unmount (they leaked before)
31
+ */
32
+ export declare function useAudioVisualizer({ uniqueId, waveform, width, height, registry, }: UseAudioVisualizerOptions): AudioVisualizer;
18
33
  export default useAudioVisualizer;
@@ -0,0 +1,86 @@
1
+ import { CaptionSegment } from '../../utils/captions';
2
+ import * as React from "react";
3
+ import * as PIXI from "pixi.js";
4
+ /** Style fields read from `transformation`. All optional; defaults suit a bottom caption. */
5
+ export interface PixiCaptionsTransformation {
6
+ x?: number;
7
+ y?: number;
8
+ fontFamily?: string;
9
+ fontWeight?: string | number;
10
+ fontSize?: number;
11
+ fill?: string;
12
+ stroke?: string | number | null;
13
+ strokeWidth?: number;
14
+ dropShadow?: boolean;
15
+ dropShadowColor?: string | number;
16
+ dropShadowBlur?: number;
17
+ dropShadowAlpha?: number;
18
+ dropShadowAngle?: number;
19
+ dropShadowDistance?: number;
20
+ wordWrapWidth?: number;
21
+ align?: string;
22
+ padding?: number;
23
+ /** Active-word colour. */
24
+ highlightColor?: string;
25
+ /** Extra px between words, on top of the space. */
26
+ wordSpacing?: number;
27
+ /** Selects the render mode (see `captionModeFor`). */
28
+ captionStyleId?: string | null;
29
+ /** Background of the `boxed` modes: hex, rgb() or rgba(). */
30
+ captionBgColor?: string;
31
+ textTransform?: "none" | "uppercase" | "lowercase";
32
+ /** Pill behind the active word in `wordbox`. */
33
+ captionActiveWordBg?: string;
34
+ }
35
+ export interface PixiCaptionsTrackProps {
36
+ /** Cue list. Build one with `parseSubtitles`, `groupWordsIntoSegments` or `normalizeCaptionSegments`. */
37
+ segments: ReadonlyArray<CaptionSegment>;
38
+ uniqueId: string;
39
+ transformation?: PixiCaptionsTransformation;
40
+ /** Fallback render-mode id when `transformation.captionStyleId` is unset. */
41
+ style?: string | null;
42
+ visible?: boolean;
43
+ disabled?: boolean;
44
+ /** Caption item start/end on the timeline (s). Used to detect clip-local cue times. */
45
+ startAt?: number;
46
+ endAt?: number;
47
+ /**
48
+ * Pin the caption to this master-timeline time (seconds) instead of following the playhead.
49
+ * Makes the output a pure function of time: use it for frame-exact export.
50
+ */
51
+ currentTime?: number;
52
+ onContainerRefReady?: (uniqueId: string, ref: React.RefObject<PIXI.Container | null>) => void;
53
+ /** Click on the caption (the invisible hit area). */
54
+ onClick?: (uniqueId: string, event: unknown) => void;
55
+ mouseOverSpriteRef?: {
56
+ current?: unknown;
57
+ };
58
+ }
59
+ /**
60
+ * PixiCaptionsTrack — word-timed (karaoke) captions on the Pixi canvas.
61
+ *
62
+ * Ported from the Clippy editor. The frame is a PURE function of (style, words, t): the playhead
63
+ * picks the active word (`sampleCaptionAt`), the mode turns that into a look (`wordVisualFor`),
64
+ * and `layoutCaptionWords` places the words. No GSAP tweens per word, so scrub / seek / reverse
65
+ * need no tween state and the editor, a server render and an exported frame agree.
66
+ *
67
+ * Modes (by `captionStyleId`): pop, glow, boxed, vhs, wordbox, punch, slam, glowpop, springpop,
68
+ * and `none` (static line). See `captionModeFor`.
69
+ *
70
+ * All children use coordinates RELATIVE to the caption centre and the container is placed at
71
+ * (x, y). In Pixi v8 an empty Graphics contributes a (0,0) point to getLocalBounds(); with
72
+ * canvas-absolute children the bounds would span from the canvas origin and a transformer box
73
+ * would swallow the screen.
74
+ *
75
+ * Differences from the Clippy original: boxed backgrounds accept hex / rgb() / rgba() (it only
76
+ * read rgba()), the font/layout caches are flushed through the engine's font events, the blur
77
+ * filters are destroyed, an optional `currentTime` makes the output deterministic, and the
78
+ * `wordbox` branch no longer contains a stray unreachable statement.
79
+ */
80
+ declare const PixiCaptionsTrackInner: {
81
+ (props: PixiCaptionsTrackProps): import("react/jsx-runtime").JSX.Element;
82
+ displayName: string;
83
+ };
84
+ declare const PixiCaptionsTrack: typeof PixiCaptionsTrackInner;
85
+ export default PixiCaptionsTrack;
86
+ export { PixiCaptionsTrack };
@@ -0,0 +1,5 @@
1
+ export { default as PixiCaptionsTrack } from './PixiCaptionsTrack';
2
+ export type { PixiCaptionsTrackProps, PixiCaptionsTransformation, } from './PixiCaptionsTrack';
3
+ export { useCaptionPlayhead } from './useCaptionPlayhead';
4
+ export { useCaptionStyles } from './useCaptionStyles';
5
+ export { useEmojiTextures } from './useEmojiTextures';
@@ -0,0 +1,31 @@
1
+ import { CaptionRenderMode, CaptionSample, CaptionSegment } from '../../utils/captions';
2
+ import type * as PIXI from "pixi.js";
3
+ export interface UseCaptionPlayheadOptions {
4
+ containerRef: React.RefObject<PIXI.Container | null>;
5
+ segments: ReadonlyArray<CaptionSegment>;
6
+ mode: CaptionRenderMode;
7
+ disabled?: boolean;
8
+ /** Caption item timeline start / end (seconds), to detect clip-local cue times. */
9
+ itemStartSec?: number;
10
+ itemEndSec?: number;
11
+ /**
12
+ * Master-timeline time in seconds. When given, the caption is a PURE function of this value,
13
+ * computed during render: no playhead subscription and no frame lag. Use it for deterministic
14
+ * export (Remotion frame / fps). When omitted, the master GSAP playhead is followed.
15
+ */
16
+ currentTime?: number;
17
+ }
18
+ /**
19
+ * What the caption shows right now: the active segment, active word and how long that word has
20
+ * been on / has left.
21
+ *
22
+ * Followed mode listens to Pixi's per-frame `onRender` (one callback per frame actually drawn,
23
+ * no second rAF loop), reads the playhead seconds from the master timeline, and only calls
24
+ * setState when something visible changed. The word's elapsed/remaining ms change every frame,
25
+ * but only matter to modes that animate within a word, so other modes do not re-render per frame.
26
+ *
27
+ * Controlled mode (`currentTime`) never subscribes. Clippy's loop sets React state from inside
28
+ * Pixi's render callback, so the committed frame lags the playhead by one; that is fine for live
29
+ * preview and wrong for an offline renderer that seeks frame by frame.
30
+ */
31
+ export declare function useCaptionPlayhead({ containerRef, segments, mode, disabled, itemStartSec, itemEndSec, currentTime, }: UseCaptionPlayheadOptions): CaptionSample;