@waveform-playlist/ui-components 11.3.1 → 12.1.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.mts CHANGED
@@ -353,8 +353,20 @@ interface PlayheadProps {
353
353
  controlsOffset?: number;
354
354
  /** Function to get current audio context time - required for smooth animation */
355
355
  getAudioContextTime?: () => number;
356
- /** Returns current playback time (auto-wraps at loop boundaries). Preferred over manual elapsed calculation. */
356
+ /**
357
+ * Returns raw playback time from the engine (auto-wraps at loop boundaries).
358
+ * This is the scheduling position — for playhead display use `visualTimeRef`
359
+ * which already has `outputLatency` and `lookAhead` subtracted.
360
+ */
357
361
  getPlaybackTime?: () => number;
362
+ /**
363
+ * Ref to the visually-aligned playback time (raw time minus `outputLatency`
364
+ * and `engine.lookAhead`), kept current by the provider's animation loop
365
+ * during playback and by pause/stop/seek paths when stopped. Use this for
366
+ * playhead positioning so it lines up with audible output and matches the
367
+ * progress fill in `ChannelWithProgress`.
368
+ */
369
+ visualTimeRef?: react__default.RefObject<number>;
358
370
  }
359
371
  /**
360
372
  * Type for custom playhead render functions.
package/dist/index.d.ts CHANGED
@@ -353,8 +353,20 @@ interface PlayheadProps {
353
353
  controlsOffset?: number;
354
354
  /** Function to get current audio context time - required for smooth animation */
355
355
  getAudioContextTime?: () => number;
356
- /** Returns current playback time (auto-wraps at loop boundaries). Preferred over manual elapsed calculation. */
356
+ /**
357
+ * Returns raw playback time from the engine (auto-wraps at loop boundaries).
358
+ * This is the scheduling position — for playhead display use `visualTimeRef`
359
+ * which already has `outputLatency` and `lookAhead` subtracted.
360
+ */
357
361
  getPlaybackTime?: () => number;
362
+ /**
363
+ * Ref to the visually-aligned playback time (raw time minus `outputLatency`
364
+ * and `engine.lookAhead`), kept current by the provider's animation loop
365
+ * during playback and by pause/stop/seek paths when stopped. Use this for
366
+ * playhead positioning so it lines up with audible output and matches the
367
+ * progress fill in `ChannelWithProgress`.
368
+ */
369
+ visualTimeRef?: react__default.RefObject<number>;
358
370
  }
359
371
  /**
360
372
  * Type for custom playhead render functions.
package/dist/index.js CHANGED
@@ -1602,6 +1602,7 @@ var PlayheadWithMarker = ({
1602
1602
  color = "#ff0000",
1603
1603
  isPlaying,
1604
1604
  currentTimeRef,
1605
+ visualTimeRef,
1605
1606
  playbackStartTimeRef,
1606
1607
  audioStartPositionRef,
1607
1608
  samplesPerPixel,
@@ -1616,7 +1617,9 @@ var PlayheadWithMarker = ({
1616
1617
  const updatePosition = () => {
1617
1618
  if (containerRef.current) {
1618
1619
  let time;
1619
- if (isPlaying) {
1620
+ if (visualTimeRef?.current !== void 0 && visualTimeRef.current !== null) {
1621
+ time = visualTimeRef.current;
1622
+ } else if (isPlaying) {
1620
1623
  if (getPlaybackTime) {
1621
1624
  time = getPlaybackTime();
1622
1625
  } else if (getAudioContextTime) {
@@ -1652,6 +1655,7 @@ var PlayheadWithMarker = ({
1652
1655
  samplesPerPixel,
1653
1656
  controlsOffset,
1654
1657
  currentTimeRef,
1658
+ visualTimeRef,
1655
1659
  playbackStartTimeRef,
1656
1660
  audioStartPositionRef,
1657
1661
  getAudioContextTime,
@@ -1659,7 +1663,7 @@ var PlayheadWithMarker = ({
1659
1663
  ]);
1660
1664
  (0, import_react9.useEffect)(() => {
1661
1665
  if (!isPlaying && containerRef.current) {
1662
- const time = currentTimeRef.current ?? 0;
1666
+ const time = visualTimeRef?.current ?? currentTimeRef.current ?? 0;
1663
1667
  const pos = time * sampleRate / samplesPerPixel + controlsOffset;
1664
1668
  containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;
1665
1669
  }
@@ -2896,6 +2900,14 @@ var StyledTimeScale = (0, import_styled_components23.withTheme)(TimeScale);
2896
2900
  // src/components/SmartScale.tsx
2897
2901
  var import_core7 = require("@waveform-playlist/core");
2898
2902
  var import_jsx_runtime27 = require("react/jsx-runtime");
2903
+ function ticksToBarBeatLabel(ticks, timeSignature, ppqn = import_core7.PPQN) {
2904
+ const barTicks = (0, import_core7.ticksPerBar)(timeSignature, ppqn);
2905
+ const beatTicks = (0, import_core7.ticksPerBeat)(timeSignature, ppqn);
2906
+ const bar = Math.floor(ticks / barTicks) + 1;
2907
+ const beatInBar = Math.floor(ticks % barTicks / beatTicks) + 1;
2908
+ if (beatInBar === 1) return `${bar}`;
2909
+ return `${bar}.${beatInBar}`;
2910
+ }
2899
2911
  var timeinfo = /* @__PURE__ */ new Map([
2900
2912
  [700, { marker: 1e3, bigStep: 500, smallStep: 100 }],
2901
2913
  [1500, { marker: 2e3, bigStep: 1e3, smallStep: 200 }],
@@ -2978,7 +2990,7 @@ var SmartScale = ({ renderTick }) => {
2978
2990
  const tickHeight = isBarLine ? timeScaleHeight : isLabelTick ? Math.floor(timeScaleHeight / 2) : Math.floor(timeScaleHeight / 5);
2979
2991
  canvasInfo2.set(pix, tickHeight);
2980
2992
  if (isLabelTick) {
2981
- const label = (0, import_core7.ticksToBarBeatLabel)(tick, timeSignature);
2993
+ const label = ticksToBarBeatLabel(tick, timeSignature);
2982
2994
  const element = renderTick ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react23.default.Fragment, { children: renderTick(label, pix) }, `bb-${tick}`) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2983
2995
  "div",
2984
2996
  {