{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "core-sample-view",
  "type": "registry:ui",
  "title": "Sample View",
  "description": "One take on a seconds axis from host-prepared data only: min/max peaks on a canvas, a PreparedSpectrogramData heatmap (magma, log frequency) or both, with a Wave / Spectrum / Both toggle. Draggable, keyboard-steppable start/end and loop handles report take-normalized positions; playheads; a dimmed extension past the take end; a seconds ruler; and an overlay slot whose children read the same geometry from context. The axis latches during an overlay drag. The canvas repaints only when its peaks, colour or size change.",
  "dependencies": [
    "@base-ui/react",
    "@webgpu/types",
    "maruaudio@>=0.0.3 <0.1.0"
  ],
  "registryDependencies": [
    "https://pluginui.com/r/core-segmented-control.json",
    "https://pluginui.com/r/core-spectrogram.json"
  ],
  "files": [
    {
      "path": "components/ui/sample-view.tsx",
      "content": "/**\n * Source: https://maru.audio/ui-kit/sample-view\n * Copyright © [Maru](https://maru.audio)\n *\n * Maru UI Kit — https://maru.audio/ui-kit\n *\n * Installed from the Maru UI registry. This file is yours now: edit it\n * freely, it will not be overwritten unless you re-run the add command.\n *\n * Keep this item’s companion files and CSS imports together. Dependencies\n * declared by the registry are installed with the source.\n */\n/**\n * SampleView — one take on a seconds axis: waveform, spectrogram or both,\n * with draggable start/end and loop handles, playheads and an overlay slot\n * (the `EnvelopeOverlay` goes there).\n *\n * The host prepares everything: `peaks` are min/max columns and `spectrogram`\n * is a bounded `PreparedSpectrogramData`. The view never decodes audio or\n * runs an FFT, so it costs the same in a module face, Studio or a webview.\n *\n * ## One time axis\n *\n * The horizontal domain is `[0, axisSeconds]` (default: the take's length).\n * The take fills `[0, durationSeconds]`; a longer axis leaves a dimmed\n * extension on the right where an envelope can run past the audio. Handles\n * and playheads are take-normalized (0..1, the module's `sample.start` units)\n * and `onRegionChange` reports them in those units. The overlay reads the\n * same geometry from context (`useSampleViewGeometry`), and while an overlay\n * gesture is active the axis is latched so the view never rescales under the\n * pointer; it catches up on release.\n *\n * ## Cost\n *\n * The waveform canvas repaints only when its peaks, colour, take fraction or\n * size change, and the prepared spectrogram only when its data or axis does.\n * Handle drags, playhead updates and envelope edits re-render DOM/SVG only.\n */\n\nimport {\n  memo,\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  type CSSProperties,\n  type KeyboardEvent,\n  type ReactNode,\n} from \"react\"\nimport { token } from \"maruaudio/ui/shared/theme\"\nimport { useSurfacePointer } from \"maruaudio/ui/shared/use-surface-pointer\"\nimport type { PreparedSpectrogramData } from \"maruaudio/ui/shared/prepared-spectrogram\"\nimport {\n  Spectrogram,\n  type SpectrogramColorScaleName,\n} from \"@/components/ui/spectrogram\"\nimport { SegmentedControl } from \"@/components/ui/segmented-control\"\nimport {\n  SampleViewContext,\n  type SampleViewGeometry,\n} from \"maruaudio/ui/shared/sample-view-context\"\nimport {\n  axisFractionToTakePosition,\n  formatSampleViewSeconds,\n  moveRegionHandle,\n  reducePeaks,\n  regionHandleBounds,\n  regionHandleKeyStep,\n  sampleViewTicks,\n  secondsToAxisFraction,\n  type SampleViewPeaks,\n  type SampleViewRegion,\n  type SampleViewRegionHandle,\n} from \"maruaudio/ui/shared/sample-view-geometry\"\n\nexport type SampleViewMode = \"waveform\" | \"spectrogram\" | \"combined\"\n\nexport const SAMPLE_VIEW_MODES: readonly SampleViewMode[] = [\n  \"waveform\",\n  \"spectrogram\",\n  \"combined\",\n]\n\nexport interface SampleViewPlayhead {\n  readonly id: string | number\n  /** Take-normalized position, 0..1. */\n  readonly position: number\n  readonly color?: string\n}\n\nexport interface SampleViewProps {\n  /** Host-prepared min/max peaks across the take. */\n  readonly peaks?: SampleViewPeaks | null\n  /** Host-prepared spectrogram of the take. */\n  readonly spectrogram?: PreparedSpectrogramData | null\n  /** The take's length in seconds. */\n  readonly durationSeconds: number\n  /** Axis length in seconds; at least the take. See `sampleViewAxisSeconds`. */\n  readonly axisSeconds?: number\n\n  /** Controlled mode. */\n  readonly mode?: SampleViewMode\n  readonly defaultMode?: SampleViewMode\n  readonly onModeChange?: (mode: SampleViewMode) => void\n  /** Show the Wave / Spectrum / Both toggle. Defaults to true. */\n  readonly showModeToggle?: boolean\n  /** Extra content beside the mode toggle. */\n  readonly toolbar?: ReactNode\n\n  /** Take-normalized start/end (and optional loop) handles. */\n  readonly region?: SampleViewRegion\n  readonly onRegionChange?: (\n    region: SampleViewRegion,\n    handle: SampleViewRegionHandle\n  ) => void\n  readonly onRegionChangeEnd?: (\n    region: SampleViewRegion,\n    handle: SampleViewRegionHandle\n  ) => void\n  /** Show the loop handles (when the region has loop points). */\n  readonly loop?: boolean\n  /** Minimum take-normalized distance between paired handles. */\n  readonly minRegionGap?: number\n\n  readonly playheads?: readonly SampleViewPlayhead[]\n  /** Drawn above the audio, below the handles; reads `useSampleViewGeometry`. */\n  readonly overlay?: ReactNode\n\n  readonly height?: number\n  /** Show the seconds ruler under the view. Defaults to true. */\n  readonly showRuler?: boolean\n  readonly waveformColor?: string\n  readonly colorScale?: SpectrogramColorScaleName\n  readonly minFrequency?: number\n  readonly maxFrequency?: number\n  readonly showFrequencyAxis?: boolean\n  /** Accessible name. Defaults to \"Sample\". */\n  readonly label?: string\n  /** Shown when there is nothing to draw. */\n  readonly emptyLabel?: ReactNode\n  readonly disabled?: boolean\n  readonly className?: string\n  readonly style?: CSSProperties\n}\n\nconst MODE_LABELS: Record<SampleViewMode, string> = {\n  waveform: \"Wave\",\n  spectrogram: \"Spectrum\",\n  combined: \"Both\",\n}\n\nconst HANDLE_LABELS: Record<SampleViewRegionHandle, string> = {\n  start: \"Sample start\",\n  end: \"Sample end\",\n  loopStart: \"Loop start\",\n  loopEnd: \"Loop end\",\n}\n\nconst HANDLE_TABS: Record<SampleViewRegionHandle, string> = {\n  start: \"S\",\n  end: \"E\",\n  loopStart: \"L\",\n  loopEnd: \"L\",\n}\n\nconst EXTENSION_SHADE =\n  \"color-mix(in oklab, var(--uikit-surface, #14161d) 62%, transparent)\"\nconst OUTSIDE_REGION_SHADE =\n  \"color-mix(in oklab, var(--uikit-surface, #14161d) 55%, transparent)\"\n\n/** Waveform columns on a canvas; repaints only when its inputs change. */\nconst WaveformCanvas = memo(function WaveformCanvas({\n  peaks,\n  takeFraction,\n  color,\n  opacity,\n}: {\n  readonly peaks: SampleViewPeaks | null | undefined\n  readonly takeFraction: number\n  readonly color: string\n  readonly opacity: number\n}) {\n  const canvasRef = useRef<HTMLCanvasElement | null>(null)\n  useEffect(() => {\n    const canvas = canvasRef.current\n    const ctx = canvas?.getContext?.(\"2d\")\n    if (!canvas || !ctx) return\n    const paint = () => {\n      const width = canvas.clientWidth\n      const height = canvas.clientHeight\n      if (width < 1 || height < 1) return\n      const dpr = Math.min(window.devicePixelRatio || 1, 2)\n      const w = Math.max(1, Math.min(4096, Math.round(width * dpr)))\n      const h = Math.max(1, Math.min(2048, Math.round(height * dpr)))\n      if (canvas.width !== w) canvas.width = w\n      if (canvas.height !== h) canvas.height = h\n      ctx.clearRect(0, 0, w, h)\n      if (!peaks) return\n      ctx.fillStyle = window.getComputedStyle(canvas).color || \"#9aa4b8\"\n      const { min, max } = reducePeaks(peaks, w, takeFraction)\n      const mid = h / 2\n      const gain = mid * 0.94\n      for (let x = 0; x < w; x += 1) {\n        const top = mid - max[x]! * gain\n        const bottom = mid - min[x]! * gain\n        ctx.fillRect(x, top, 1, Math.max(dpr, bottom - top))\n      }\n    }\n    paint()\n    const observer =\n      typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(paint)\n    observer?.observe(canvas)\n    return () => observer?.disconnect()\n  }, [peaks, takeFraction, color])\n  return (\n    <canvas\n      ref={canvasRef}\n      aria-hidden=\"true\"\n      data-sample-view-waveform=\"\"\n      style={{\n        position: \"absolute\",\n        inset: 0,\n        width: \"100%\",\n        height: \"100%\",\n        display: \"block\",\n        color,\n        opacity,\n        pointerEvents: \"none\",\n      }}\n    />\n  )\n})\n\nconst SpectrogramLayer = memo(function SpectrogramLayer({\n  spectrogram,\n  axisSeconds,\n  height,\n  colorScale,\n  minFrequency,\n  maxFrequency,\n  showAxis,\n}: {\n  readonly spectrogram: PreparedSpectrogramData\n  readonly axisSeconds: number\n  readonly height: number\n  readonly colorScale: SpectrogramColorScaleName\n  readonly minFrequency?: number\n  readonly maxFrequency?: number\n  readonly showAxis: boolean\n}) {\n  return (\n    <Spectrogram\n      mode=\"prepared\"\n      prepared={spectrogram}\n      durationSeconds={axisSeconds}\n      height={height}\n      width=\"100%\"\n      colorScale={colorScale}\n      minFrequency={minFrequency}\n      maxFrequency={maxFrequency}\n      showAxis={showAxis}\n      aria-label=\"Spectrogram\"\n      style={{\n        position: \"absolute\",\n        inset: 0,\n        border: 0,\n        borderRadius: 0,\n        background: \"transparent\",\n        pointerEvents: \"none\",\n      }}\n    />\n  )\n})\n\nfunction RegionHandle({\n  handle,\n  region,\n  geometry,\n  minGap,\n  onChange,\n  onChangeEnd,\n}: {\n  readonly handle: SampleViewRegionHandle\n  readonly region: SampleViewRegion\n  readonly geometry: SampleViewGeometry\n  readonly minGap: number\n  readonly onChange?: SampleViewProps[\"onRegionChange\"]\n  readonly onChangeEnd?: SampleViewProps[\"onRegionChangeEnd\"]\n}) {\n  const latest = useRef(region)\n  latest.current = region\n  const value =\n    handle === \"loopStart\"\n      ? (region.loopStart ?? 0)\n      : handle === \"loopEnd\"\n        ? (region.loopEnd ?? 1)\n        : region[handle]\n  const bounds = regionHandleBounds(region, handle, minGap)\n  const editable = !geometry.disabled && onChange !== undefined\n  const loop = handle === \"loopStart\" || handle === \"loopEnd\"\n  const color = loop ? token.accent2 : token.text\n\n  const drag = useSurfacePointer(\n    (state) => {\n      const rect = geometry.surfaceRef.current?.getBoundingClientRect()\n      if (!rect || rect.width <= 0) return\n      const position = axisFractionToTakePosition(\n        (state.clientX - rect.left) / rect.width,\n        geometry.durationSeconds,\n        geometry.axisSeconds\n      )\n      const next = moveRegionHandle(latest.current, handle, position, minGap)\n      latest.current = next\n      onChange?.(next, handle)\n    },\n    {\n      disabled: !editable,\n      onEnd: () => onChangeEnd?.(latest.current, handle),\n    }\n  )\n\n  const onKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n    if (!editable) return\n    const next = regionHandleKeyStep(\n      latest.current,\n      handle,\n      event.key,\n      event.shiftKey,\n      minGap\n    )\n    if (!next) return\n    event.preventDefault()\n    latest.current = next\n    onChange?.(next, handle)\n    onChangeEnd?.(next, handle)\n  }\n\n  const x =\n    secondsToAxisFraction(value * geometry.durationSeconds, geometry.axisSeconds) *\n    100\n  const seconds = value * geometry.durationSeconds\n  return (\n    <div\n      role=\"slider\"\n      tabIndex={editable ? 0 : -1}\n      aria-label={HANDLE_LABELS[handle]}\n      aria-orientation=\"horizontal\"\n      aria-valuemin={bounds.min}\n      aria-valuemax={bounds.max}\n      aria-valuenow={value}\n      aria-valuetext={`${formatSampleViewSeconds(seconds)} (${Math.round(value * 100)}%)`}\n      aria-disabled={!editable || undefined}\n      data-sample-view-handle={handle}\n      className=\"uikit-control\"\n      onPointerDown={drag.onPointerDown}\n      onKeyDown={onKeyDown}\n      style={{\n        position: \"absolute\",\n        top: 0,\n        bottom: 0,\n        left: `${x}%`,\n        width: 12,\n        marginLeft: -6,\n        zIndex: 3,\n        cursor: editable ? \"ew-resize\" : \"default\",\n        touchAction: \"none\",\n        color,\n        outlineOffset: -2,\n      }}\n    >\n      <span\n        aria-hidden=\"true\"\n        style={{\n          position: \"absolute\",\n          top: 0,\n          bottom: 0,\n          left: 5.5,\n          width: 1,\n          background: \"currentColor\",\n          opacity: drag.dragging ? 1 : 0.85,\n          boxShadow: \"0 0 0 1px rgba(0,0,0,0.35)\",\n        }}\n      />\n      <span\n        aria-hidden=\"true\"\n        style={{\n          position: \"absolute\",\n          left: handle === \"end\" || handle === \"loopEnd\" ? -7 : 6,\n          [loop ? \"top\" : \"bottom\"]: 0,\n          minWidth: 13,\n          height: 14,\n          padding: \"0 3px\",\n          borderRadius: 3,\n          background: \"currentColor\",\n          fontFamily: token.fontMono,\n          fontSize: 9,\n          fontWeight: 700,\n          lineHeight: \"14px\",\n          textAlign: \"center\",\n        }}\n      >\n        <span style={{ color: token.surface }}>{HANDLE_TABS[handle]}</span>\n      </span>\n    </div>\n  )\n}\n\nexport function SampleView({\n  peaks,\n  spectrogram,\n  durationSeconds,\n  axisSeconds,\n  mode: controlledMode,\n  defaultMode = \"waveform\",\n  onModeChange,\n  showModeToggle = true,\n  toolbar,\n  region,\n  onRegionChange,\n  onRegionChangeEnd,\n  loop = false,\n  minRegionGap = 0.001,\n  playheads,\n  overlay,\n  height = 160,\n  showRuler = true,\n  waveformColor,\n  colorScale = \"magma\",\n  minFrequency,\n  maxFrequency,\n  showFrequencyAxis = false,\n  label = \"Sample\",\n  emptyLabel,\n  disabled = false,\n  className,\n  style,\n}: SampleViewProps) {\n  const [ownMode, setOwnMode] = useState<SampleViewMode>(defaultMode)\n  const mode = controlledMode ?? ownMode\n  const chooseMode = useCallback(\n    (next: SampleViewMode) => {\n      if (controlledMode === undefined) setOwnMode(next)\n      onModeChange?.(next)\n    },\n    [controlledMode, onModeChange]\n  )\n\n  const duration = Math.max(0, Number.isFinite(durationSeconds) ? durationSeconds : 0)\n  const requestedAxis = Math.max(\n    duration,\n    axisSeconds !== undefined && Number.isFinite(axisSeconds) ? axisSeconds : 0\n  ) || 1\n  // An overlay gesture latches the axis so the view cannot rescale under it.\n  const [latched, setLatched] = useState<number | null>(null)\n  const axis = latched ?? requestedAxis\n  const axisRef = useRef(axis)\n  axisRef.current = axis\n  const durationRef = useRef(duration)\n  durationRef.current = duration\n  const surfaceRef = useRef<HTMLDivElement | null>(null)\n  const gestures = useRef(0)\n\n  const geometry = useMemo<SampleViewGeometry>(\n    () => ({\n      axisSeconds: axis,\n      durationSeconds: duration,\n      takeFraction: Math.min(1, duration / axis),\n      height,\n      disabled,\n      surfaceRef,\n      clientXToSeconds(clientX: number) {\n        const rect = surfaceRef.current?.getBoundingClientRect()\n        if (!rect || rect.width <= 0) return 0\n        return ((clientX - rect.left) / rect.width) * axisRef.current\n      },\n      beginGesture() {\n        gestures.current += 1\n        setLatched((current) => current ?? axisRef.current)\n      },\n      endGesture() {\n        gestures.current = Math.max(0, gestures.current - 1)\n        if (gestures.current === 0) setLatched(null)\n      },\n    }),\n    [axis, duration, height, disabled]\n  )\n\n  const showWaveform = mode !== \"spectrogram\"\n  const showSpectrogram = mode !== \"waveform\" && spectrogram\n  const takeFraction = geometry.takeFraction\n  const hasAudio = Boolean(peaks || spectrogram)\n  const handles: SampleViewRegionHandle[] = region\n    ? [\n        \"start\",\n        \"end\",\n        ...(loop && region.loopStart !== undefined && region.loopEnd !== undefined\n          ? ([\"loopStart\", \"loopEnd\"] as const)\n          : []),\n      ]\n    : []\n  const toFraction = (position: number) =>\n    secondsToAxisFraction(position * duration, axis) * 100\n\n  return (\n    <div\n      role=\"group\"\n      aria-label={label}\n      data-sample-view=\"\"\n      data-mode={mode}\n      className={className}\n      style={{\n        display: \"flex\",\n        flexDirection: \"column\",\n        gap: 6,\n        minWidth: 0,\n        fontFamily: token.font,\n        color: token.text,\n        ...style,\n      }}\n    >\n      {showModeToggle || toolbar ? (\n        <div\n          data-sample-view-toolbar=\"\"\n          style={{\n            display: \"flex\",\n            flexWrap: \"wrap\",\n            alignItems: \"center\",\n            justifyContent: \"space-between\",\n            gap: 6,\n            minWidth: 0,\n          }}\n        >\n          {showModeToggle ? (\n            <SegmentedControl<SampleViewMode>\n              aria-label={`${label} view`}\n              value={mode}\n              onValueChange={chooseMode}\n              size=\"sm\"\n              disabled={disabled}\n              options={SAMPLE_VIEW_MODES.map((value) => ({\n                value,\n                label: MODE_LABELS[value],\n                disabled: value !== \"waveform\" && !spectrogram,\n                \"aria-description\":\n                  value !== \"waveform\" && !spectrogram\n                    ? \"No spectrogram for this take\"\n                    : undefined,\n              }))}\n            />\n          ) : (\n            <span />\n          )}\n          {toolbar}\n        </div>\n      ) : null}\n\n      <div\n        ref={surfaceRef}\n        data-sample-view-surface=\"\"\n        style={{\n          position: \"relative\",\n          height,\n          minWidth: 0,\n          overflow: \"hidden\",\n          isolation: \"isolate\",\n          background: token.surface,\n          border: `1px solid ${token.border}`,\n          borderRadius: token.radius,\n          touchAction: \"none\",\n          opacity: disabled ? 0.6 : 1,\n        }}\n      >\n        {showSpectrogram ? (\n          <SpectrogramLayer\n            spectrogram={spectrogram}\n            axisSeconds={axis}\n            height={height}\n            colorScale={colorScale}\n            minFrequency={minFrequency}\n            maxFrequency={maxFrequency}\n            showAxis={showFrequencyAxis}\n          />\n        ) : null}\n        {showWaveform ? (\n          <WaveformCanvas\n            peaks={peaks}\n            takeFraction={takeFraction}\n            color={waveformColor ?? (mode === \"combined\" ? \"#f8fafc\" : token.accent)}\n            opacity={mode === \"combined\" ? 0.55 : 0.9}\n          />\n        ) : null}\n        {mode === \"spectrogram\" && !spectrogram ? (\n          <div\n            data-sample-view-unavailable=\"\"\n            style={{\n              position: \"absolute\",\n              inset: 0,\n              display: \"grid\",\n              placeItems: \"center\",\n              fontSize: 11,\n              color: token.textMuted,\n            }}\n          >\n            No spectrogram for this take\n          </div>\n        ) : null}\n\n        {takeFraction < 1 ? (\n          <div\n            aria-hidden=\"true\"\n            data-sample-view-extension=\"\"\n            style={{\n              position: \"absolute\",\n              top: 0,\n              bottom: 0,\n              left: `${takeFraction * 100}%`,\n              right: 0,\n              background: EXTENSION_SHADE,\n              borderLeft: `1px dashed ${token.border}`,\n              pointerEvents: \"none\",\n            }}\n          />\n        ) : null}\n\n        {region ? (\n          <>\n            <div\n              aria-hidden=\"true\"\n              style={{\n                position: \"absolute\",\n                top: 0,\n                bottom: 0,\n                left: 0,\n                width: `${toFraction(region.start)}%`,\n                background: OUTSIDE_REGION_SHADE,\n                pointerEvents: \"none\",\n              }}\n            />\n            <div\n              aria-hidden=\"true\"\n              style={{\n                position: \"absolute\",\n                top: 0,\n                bottom: 0,\n                left: `${toFraction(region.end)}%`,\n                width: `${Math.max(0, takeFraction * 100 - toFraction(region.end))}%`,\n                background: OUTSIDE_REGION_SHADE,\n                pointerEvents: \"none\",\n              }}\n            />\n            {handles.includes(\"loopStart\") ? (\n              <div\n                aria-hidden=\"true\"\n                data-sample-view-loop=\"\"\n                style={{\n                  position: \"absolute\",\n                  top: 0,\n                  height: 3,\n                  left: `${toFraction(region.loopStart ?? 0)}%`,\n                  width: `${Math.max(0, toFraction(region.loopEnd ?? 1) - toFraction(region.loopStart ?? 0))}%`,\n                  background: token.accent2,\n                  opacity: 0.8,\n                  pointerEvents: \"none\",\n                }}\n              />\n            ) : null}\n          </>\n        ) : null}\n\n        {overlay ? (\n          <SampleViewContext.Provider value={geometry}>\n            <div\n              data-sample-view-overlay=\"\"\n              style={{ position: \"absolute\", inset: 0, zIndex: 4, pointerEvents: \"none\" }}\n            >\n              {overlay}\n            </div>\n          </SampleViewContext.Provider>\n        ) : null}\n\n        {region\n          ? handles.map((handle) => (\n              <RegionHandle\n                key={handle}\n                handle={handle}\n                region={region}\n                geometry={geometry}\n                minGap={minRegionGap}\n                onChange={onRegionChange}\n                onChangeEnd={onRegionChangeEnd}\n              />\n            ))\n          : null}\n\n        {playheads && playheads.length > 0 ? (\n          <div\n            aria-hidden=\"true\"\n            data-sample-view-playheads={playheads.length}\n            style={{ position: \"absolute\", inset: 0, zIndex: 5, pointerEvents: \"none\" }}\n          >\n            {playheads.map((playhead) => (\n              <span\n                key={playhead.id}\n                data-sample-view-playhead={playhead.id}\n                style={{\n                  position: \"absolute\",\n                  top: 0,\n                  bottom: 0,\n                  width: 1,\n                  left: `${toFraction(Math.max(0, Math.min(1, playhead.position)))}%`,\n                  background: playhead.color ?? \"#f8fafc\",\n                  boxShadow: \"0 0 4px rgba(255,255,255,0.8)\",\n                }}\n              />\n            ))}\n          </div>\n        ) : null}\n\n        {!hasAudio ? (\n          <div\n            data-sample-view-empty=\"\"\n            style={{\n              position: \"absolute\",\n              inset: 0,\n              display: \"grid\",\n              placeItems: \"center\",\n              padding: 12,\n              textAlign: \"center\",\n              fontSize: 11,\n              color: token.textMuted,\n              pointerEvents: \"none\",\n            }}\n          >\n            {emptyLabel ?? \"No take loaded\"}\n          </div>\n        ) : null}\n      </div>\n\n      {showRuler ? (\n        <div\n          aria-hidden=\"true\"\n          data-sample-view-ruler=\"\"\n          style={{\n            position: \"relative\",\n            height: 12,\n            fontFamily: token.fontMono,\n            fontSize: 9,\n            fontVariantNumeric: \"tabular-nums\",\n            color: token.textMuted,\n            overflow: \"hidden\",\n          }}\n        >\n          {sampleViewTicks(axis).map((tick, index, ticks) => (\n            <span\n              key={tick}\n              style={{\n                position: \"absolute\",\n                top: 0,\n                left: `${secondsToAxisFraction(tick, axis) * 100}%`,\n                transform:\n                  index === 0\n                    ? undefined\n                    : index === ticks.length - 1 && tick >= axis - 1e-6\n                      ? \"translateX(-100%)\"\n                      : \"translateX(-50%)\",\n                whiteSpace: \"nowrap\",\n                opacity: tick > duration + 1e-6 ? 0.55 : 1,\n              }}\n            >\n              {formatSampleViewSeconds(tick)}\n            </span>\n          ))}\n        </div>\n      ) : null}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@ui/sample-view.tsx"
    }
  ]
}
