@waveform-playlist/browser 7.1.3 → 8.0.0

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.
package/dist/index.d.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import { Analyser } from 'tone';
2
- import { BaseContext } from 'tone';
3
2
  import { default as default_2 } from 'react';
4
3
  import { default as default_3 } from 'waveform-data';
4
+ import { DragCancelEvent } from '@dnd-kit/core';
5
5
  import { DragEndEvent } from '@dnd-kit/core';
6
6
  import { DragMoveEvent } from '@dnd-kit/core';
7
7
  import { DragStartEvent } from '@dnd-kit/core';
8
- import { Fade as Fade_2 } from '@waveform-playlist/core';
8
+ import { EngineState } from '@waveform-playlist/engine';
9
9
  import { Gain } from 'tone';
10
10
  import { InputNode } from 'tone';
11
11
  import { MediaElementPlayout } from '@waveform-playlist/media-element-playout';
12
12
  import { Modifier } from '@dnd-kit/core';
13
13
  import { MutableRefObject } from 'react';
14
+ import { PlaylistEngine } from '@waveform-playlist/engine';
14
15
  import { Provider } from 'react';
15
16
  import react__default from 'react';
16
17
  import { ReactNode } from 'react';
@@ -19,7 +20,6 @@ import { SensorDescriptor } from '@dnd-kit/core';
19
20
  import { SensorOptions } from '@dnd-kit/core';
20
21
  import * as Tone from 'tone';
21
22
  import { ToneAudioNode } from 'tone';
22
- import { Track } from '@waveform-playlist/core';
23
23
  import { Volume } from 'tone';
24
24
 
25
25
  export declare interface ActiveEffect {
@@ -262,16 +262,6 @@ export declare const AutomaticScrollCheckbox: default_2.FC<{
262
262
  */
263
263
  declare type Bits = 8 | 16;
264
264
 
265
- declare interface ClipInfo {
266
- buffer: AudioBuffer;
267
- startTime: number;
268
- duration: number;
269
- offset: number;
270
- fadeIn?: Fade_2;
271
- fadeOut?: Fade_2;
272
- gain: number;
273
- }
274
-
275
265
  declare interface ClipPeaks {
276
266
  clipId: string;
277
267
  trackName: string;
@@ -630,6 +620,8 @@ export declare const MasterVolumeControl: default_2.FC<{
630
620
  export declare interface MasterVolumeControls {
631
621
  masterVolume: number;
632
622
  setMasterVolume: (volume: number) => void;
623
+ /** Ref holding the current masterVolume for seeding a fresh engine. */
624
+ masterVolumeRef: React.RefObject<number>;
633
625
  }
634
626
 
635
627
  export declare interface MediaElementAnimationContextValue {
@@ -1004,7 +996,7 @@ declare interface PlaylistDataContextValue {
1004
996
  show: boolean;
1005
997
  width: number;
1006
998
  };
1007
- playoutRef: default_2.RefObject<TonePlayout | null>;
999
+ playoutRef: default_2.RefObject<PlaylistEngine | null>;
1008
1000
  samplesPerPixel: number;
1009
1001
  timeFormat: TimeFormat;
1010
1002
  masterVolume: number;
@@ -1018,6 +1010,9 @@ declare interface PlaylistDataContextValue {
1018
1010
  isReady: boolean;
1019
1011
  /** Whether tracks are rendered in mono mode */
1020
1012
  mono: boolean;
1013
+ /** Ref set by useClipDragHandlers during boundary trim drags.
1014
+ * When true, loadAudio skips engine rebuild — visual updates flow via React state only. */
1015
+ isDraggingRef: default_2.MutableRefObject<boolean>;
1021
1016
  }
1022
1017
 
1023
1018
  declare interface PlaylistStateContextValue {
@@ -1246,88 +1241,6 @@ export declare const TimeFormatSelect: default_2.FC<{
1246
1241
 
1247
1242
  export { Tone }
1248
1243
 
1249
- declare class TonePlayout {
1250
- private tracks;
1251
- private masterVolume;
1252
- private isInitialized;
1253
- private soloedTracks;
1254
- private manualMuteState;
1255
- private effectsCleanup?;
1256
- private onPlaybackCompleteCallback?;
1257
- private activeTracks;
1258
- private playbackSessionId;
1259
- constructor(options?: TonePlayoutOptions);
1260
- private gainToDb;
1261
- init(): Promise<void>;
1262
- addTrack(trackOptions: ToneTrackOptions): ToneTrack;
1263
- /**
1264
- * Apply solo muting after all tracks have been added.
1265
- * Call this after adding all tracks to ensure solo logic is applied correctly.
1266
- */
1267
- applyInitialSoloState(): void;
1268
- removeTrack(trackId: string): void;
1269
- getTrack(trackId: string): ToneTrack | undefined;
1270
- play(when?: number, offset?: number, duration?: number): void;
1271
- pause(): void;
1272
- stop(): void;
1273
- setMasterGain(gain: number): void;
1274
- setSolo(trackId: string, soloed: boolean): void;
1275
- private updateSoloMuting;
1276
- setMute(trackId: string, muted: boolean): void;
1277
- getCurrentTime(): number;
1278
- seekTo(time: number): void;
1279
- dispose(): void;
1280
- get context(): BaseContext;
1281
- get sampleRate(): number;
1282
- setOnPlaybackComplete(callback: () => void): void;
1283
- }
1284
-
1285
- declare interface TonePlayoutOptions {
1286
- tracks?: ToneTrack[];
1287
- masterGain?: number;
1288
- effects?: EffectsFunction;
1289
- }
1290
-
1291
- declare class ToneTrack {
1292
- private clips;
1293
- private volumeNode;
1294
- private panNode;
1295
- private muteGain;
1296
- private track;
1297
- private effectsCleanup?;
1298
- private onStopCallback?;
1299
- private activePlayers;
1300
- constructor(options: ToneTrackOptions);
1301
- /**
1302
- * Schedule fade envelopes for a clip at the given start time
1303
- */
1304
- private scheduleFades;
1305
- private gainToDb;
1306
- setVolume(gain: number): void;
1307
- setPan(pan: number): void;
1308
- setMute(muted: boolean): void;
1309
- setSolo(soloed: boolean): void;
1310
- play(when?: number, offset?: number, duration?: number): void;
1311
- pause(): void;
1312
- stop(when?: number): void;
1313
- dispose(): void;
1314
- get id(): string;
1315
- get duration(): number;
1316
- get buffer(): AudioBuffer;
1317
- get isPlaying(): boolean;
1318
- get muted(): boolean;
1319
- get startTime(): number;
1320
- setOnStopCallback(callback: () => void): void;
1321
- }
1322
-
1323
- declare interface ToneTrackOptions {
1324
- buffer?: AudioBuffer;
1325
- clips?: ClipInfo[];
1326
- track: Track;
1327
- effects?: TrackEffectsFunction;
1328
- destination?: ToneAudioNode;
1329
- }
1330
-
1331
1244
  export declare interface TrackActiveEffect {
1332
1245
  instanceId: string;
1333
1246
  effectId: string;
@@ -1601,13 +1514,22 @@ declare interface UseAudioTracksOptions {
1601
1514
  * Provides drag handlers and collision modifier for use with @dnd-kit/core DndContext.
1602
1515
  * Handles both clip movement (dragging entire clips) and boundary trimming (adjusting clip edges).
1603
1516
  *
1517
+ * **Move:** `onDragEnd` delegates to `engine.moveClip()` in one shot.
1518
+ *
1519
+ * **Trim:** `onDragMove` updates React state per-frame via `onTracksChange` for smooth
1520
+ * visual feedback (using cumulative deltas from the original clip snapshot). `isDraggingRef`
1521
+ * prevents loadAudio from rebuilding the engine during the drag, so the engine keeps the
1522
+ * original clip positions. On drag end, `engine.trimClip()` commits the final delta.
1523
+ *
1604
1524
  * @example
1605
1525
  * ```tsx
1606
- * const { onDragStart, onDragMove, onDragEnd, collisionModifier } = useClipDragHandlers({
1526
+ * const { onDragStart, onDragMove, onDragEnd, onDragCancel, collisionModifier } = useClipDragHandlers({
1607
1527
  * tracks,
1608
1528
  * onTracksChange: setTracks,
1609
1529
  * samplesPerPixel,
1610
1530
  * sampleRate,
1531
+ * engineRef: playoutRef,
1532
+ * isDraggingRef,
1611
1533
  * });
1612
1534
  *
1613
1535
  * return (
@@ -1615,6 +1537,7 @@ declare interface UseAudioTracksOptions {
1615
1537
  * onDragStart={onDragStart}
1616
1538
  * onDragMove={onDragMove}
1617
1539
  * onDragEnd={onDragEnd}
1540
+ * onDragCancel={onDragCancel}
1618
1541
  * modifiers={[restrictToHorizontalAxis, collisionModifier]}
1619
1542
  * >
1620
1543
  * <Waveform showClipHeaders={true} />
@@ -1622,10 +1545,11 @@ declare interface UseAudioTracksOptions {
1622
1545
  * );
1623
1546
  * ```
1624
1547
  */
1625
- export declare function useClipDragHandlers({ tracks, onTracksChange, samplesPerPixel, sampleRate, }: UseClipDragHandlersOptions): {
1548
+ export declare function useClipDragHandlers({ tracks, onTracksChange, samplesPerPixel, sampleRate, engineRef, isDraggingRef, }: UseClipDragHandlersOptions): {
1626
1549
  onDragStart: (event: DragStartEvent) => void;
1627
1550
  onDragMove: (event: DragMoveEvent) => void;
1628
1551
  onDragEnd: (event: DragEndEvent) => void;
1552
+ onDragCancel: (_event: DragCancelEvent) => void;
1629
1553
  collisionModifier: (args: Parameters<Modifier>[0]) => {
1630
1554
  scaleX: number;
1631
1555
  scaleY: number;
@@ -1639,11 +1563,20 @@ declare interface UseClipDragHandlersOptions {
1639
1563
  onTracksChange: (tracks: ClipTrack[]) => void;
1640
1564
  samplesPerPixel: number;
1641
1565
  sampleRate: number;
1566
+ engineRef: default_2.RefObject<PlaylistEngine | null>;
1567
+ /** Ref toggled during boundary trim drags. When true, the provider's loadAudio
1568
+ * skips engine rebuilds so engine keeps original clip positions. On drag end,
1569
+ * engine.trimClip() commits the final delta. Obtain from usePlaylistData(). */
1570
+ isDraggingRef: default_2.MutableRefObject<boolean>;
1642
1571
  }
1643
1572
 
1644
1573
  /**
1645
1574
  * Hook for splitting clips at the playhead or at a specific time
1646
1575
  *
1576
+ * Splitting delegates to `engine.splitClip()` — the engine handles clip creation,
1577
+ * adapter sync, and emits statechange. The provider's statechange handler propagates
1578
+ * the updated tracks to the parent via `onTracksChange`.
1579
+ *
1647
1580
  * @param options - Configuration options
1648
1581
  * @returns Object with split functions
1649
1582
  *
@@ -1651,8 +1584,9 @@ declare interface UseClipDragHandlersOptions {
1651
1584
  * ```tsx
1652
1585
  * const { splitClipAtPlayhead } = useClipSplitting({
1653
1586
  * tracks,
1654
- * onTracksChange: setTracks,
1655
- * currentTime,
1587
+ * sampleRate,
1588
+ * samplesPerPixel,
1589
+ * engineRef: playoutRef,
1656
1590
  * });
1657
1591
  *
1658
1592
  * // In keyboard handler
@@ -1667,9 +1601,9 @@ export declare const useClipSplitting: (options: UseClipSplittingOptions) => Use
1667
1601
 
1668
1602
  declare interface UseClipSplittingOptions {
1669
1603
  tracks: ClipTrack[];
1670
- onTracksChange: (tracks: ClipTrack[]) => void;
1671
1604
  sampleRate: number;
1672
1605
  samplesPerPixel: number;
1606
+ engineRef: default_2.RefObject<PlaylistEngine | null>;
1673
1607
  }
1674
1608
 
1675
1609
  declare interface UseClipSplittingResult {
@@ -1808,27 +1742,19 @@ export declare const useMasterAnalyser: (fftSize?: number) => {
1808
1742
  };
1809
1743
 
1810
1744
  /**
1811
- * Hook for managing master volume control
1745
+ * Hook for managing master volume via PlaylistEngine delegation.
1812
1746
  *
1813
- * @example
1814
- * ```tsx
1815
- * const { masterVolume, setMasterVolume } = useMasterVolume({
1816
- * playoutRef,
1817
- * initialVolume: 1.0,
1818
- * });
1819
- *
1820
- * <MasterVolumeControl
1821
- * volume={masterVolume}
1822
- * onChange={setMasterVolume}
1823
- * />
1824
- * ```
1747
+ * setMasterVolume delegates to the engine. State is mirrored back from
1748
+ * the engine via onEngineState(), which the provider's statechange
1749
+ * handler calls on every engine event.
1825
1750
  */
1826
- export declare function useMasterVolume({ playoutRef, initialVolume, onVolumeChange, }: UseMasterVolumeProps): MasterVolumeControls;
1751
+ export declare function useMasterVolume({ engineRef, initialVolume, }: UseMasterVolumeProps): MasterVolumeControls & {
1752
+ onEngineState: (state: EngineState) => void;
1753
+ };
1827
1754
 
1828
1755
  declare interface UseMasterVolumeProps {
1829
- playoutRef: RefObject<TonePlayout | null>;
1756
+ engineRef: RefObject<PlaylistEngine | null>;
1830
1757
  initialVolume?: number;
1831
- onVolumeChange?: (volume: number) => void;
1832
1758
  }
1833
1759
 
1834
1760
  export declare const useMediaElementAnimation: () => MediaElementAnimationContextValue;
@@ -1950,11 +1876,24 @@ export declare interface UseTrackDynamicEffectsReturn {
1950
1876
  availableEffects: EffectDefinition[];
1951
1877
  }
1952
1878
 
1953
- export declare function useZoomControls({ initialSamplesPerPixel, zoomLevels, }: UseZoomControlsProps): ZoomControls;
1879
+ /**
1880
+ * Hook for managing zoom controls via PlaylistEngine delegation.
1881
+ *
1882
+ * zoomIn/zoomOut delegate to the engine. State is mirrored back from
1883
+ * the engine via onEngineState(), which the provider's statechange
1884
+ * handler calls on every engine event.
1885
+ *
1886
+ * samplesPerPixel updates use startTransition so React treats them as
1887
+ * non-urgent — during playback, animation RAF callbacks interleave
1888
+ * with the zoom re-render instead of being blocked.
1889
+ */
1890
+ export declare function useZoomControls({ engineRef, initialSamplesPerPixel, }: UseZoomControlsProps): ZoomControls & {
1891
+ onEngineState: (state: EngineState) => void;
1892
+ };
1954
1893
 
1955
1894
  declare interface UseZoomControlsProps {
1895
+ engineRef: RefObject<PlaylistEngine | null>;
1956
1896
  initialSamplesPerPixel: number;
1957
- zoomLevels?: number[];
1958
1897
  }
1959
1898
 
1960
1899
  /**
@@ -2087,6 +2026,15 @@ declare interface WaveformPlaylistProviderProps {
2087
2026
  barGap?: number;
2088
2027
  /** Width in pixels of progress bars. Default: barWidth + barGap (fills gaps). */
2089
2028
  progressBarWidth?: number;
2029
+ /** Callback when engine clip operations (move, trim, split) change tracks.
2030
+ * The provider calls this so the parent can update its tracks state without
2031
+ * triggering a full engine rebuild.
2032
+ *
2033
+ * **Important:** The parent must pass the received `tracks` reference back as
2034
+ * the `tracks` prop (i.e. `setState(tracks)`). The provider uses reference
2035
+ * identity (`tracks === engineTracksRef.current`) to detect engine-originated
2036
+ * updates and skip the expensive `loadAudio` rebuild. */
2037
+ onTracksChange?: (tracks: ClipTrack[]) => void;
2090
2038
  children: ReactNode;
2091
2039
  }
2092
2040