diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/components/AudioFilePreview/index.tsx b/packages/web-kitchensink-reactnext/src/categories/blob/react/components/AudioFilePreview/index.tsx index 1cc8b5e..126f556 100644 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/components/AudioFilePreview/index.tsx +++ b/packages/web-kitchensink-reactnext/src/categories/blob/react/components/AudioFilePreview/index.tsx @@ -6,7 +6,7 @@ import { formatSecondsDurationConcise, formatSecondsDurationPrecise, } from '@/utils/numeral'; -import {useMediaControls} from '../../hooks/media'; +import {useMediaControls} from '../../hooks/interactive'; import {useAugmentedFile} from '@/categories/blob/react'; import clsx from 'clsx'; @@ -26,6 +26,7 @@ export const AudioFilePreview = React.forwardRef { const { augmentedFile, error } = useAugmentedFile({ file, @@ -50,8 +51,11 @@ export const AudioFilePreview = React.forwardRef({ controllerRef: forwardedRef, + visualizationMode: 'waveform', }); const formId = React.useId(); @@ -79,27 +83,74 @@ export const AudioFilePreview = React.forwardRef
- - + + {visualizationMode === 'waveform' && ( + + )} +
+ + +
{enhanced && (
diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/components/ImageFilePreview/index.tsx b/packages/web-kitchensink-reactnext/src/categories/blob/react/components/ImageFilePreview/index.tsx index 102aa52..d9d0ad1 100644 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/components/ImageFilePreview/index.tsx +++ b/packages/web-kitchensink-reactnext/src/categories/blob/react/components/ImageFilePreview/index.tsx @@ -39,7 +39,7 @@ export const ImageFilePreview = React.forwardRef
-
+
{ typeof augmentedFile.metadata?.previewUrl === 'string' && ( @@ -144,7 +144,7 @@ export const ImageFilePreview = React.forwardRef diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/image.ts b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/image.ts similarity index 97% rename from packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/image.ts rename to packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/image.ts index d5dec7d..eeac848 100644 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/image.ts +++ b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/image.ts @@ -27,7 +27,7 @@ export const useImageControls = (options = {} as UseImageControlsOptions) => { const downloadLink = window.document.createElement('a'); downloadLink.download = filenameRef.current.textContent ?? 'image'; - downloadLink.href = imageRef.current.src; + downloadLink.href = imageRef.current.currentSrc; downloadLink.addEventListener('click', () => { downloadLink.remove(); }); diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/index.ts b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/index.ts new file mode 100644 index 0000000..08a2217 --- /dev/null +++ b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/index.ts @@ -0,0 +1,2 @@ +export * from './media'; +export * from './image'; diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/video.ts b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/media.ts similarity index 93% rename from packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/video.ts rename to packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/media.ts index d95930d..82cbaef 100644 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/video.ts +++ b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/interactive/media.ts @@ -3,17 +3,20 @@ import * as React from 'react'; export interface UseMediaControlsOptions { controllerRef: React.Ref; actionFormKey?: string; + visualizationMode?: string; } export const useMediaControls = ({ controllerRef: forwardedRef, actionFormKey = 'action' as const, + visualizationMode: initialVisualizationMode, }: UseMediaControlsOptions) => { const defaultRef = React.useRef(null); const ref = forwardedRef ?? defaultRef; const seekRef = React.useRef(null); const volumeRef = React.useRef(null); const filenameRef = React.useRef(null); + const [visualizationMode, setVisualizationMode] = React.useState(initialVisualizationMode); const [isPlaying, setIsPlaying] = React.useState(false); const [isSeeking, setIsSeeking] = React.useState(false); const [currentTimeDisplay, setCurrentTimeDisplay] = React.useState(); @@ -123,6 +126,10 @@ export const useMediaControls = ({ downloadLink.click(); }, [ref, filenameRef]); + const handleVisualizationModeChange: React.ChangeEventHandler = React.useCallback((e) => { + setVisualizationMode(e.currentTarget.value); + }, []); + const actions = React.useMemo(() => ({ togglePlayback, toggleSeekTimeCountMode, @@ -229,6 +236,8 @@ export const useMediaControls = ({ mediaControllerRef: ref, handleAction, filenameRef, + visualizationMode, + handleVisualizationModeChange, }), [ refreshControls, isPlaying, @@ -246,5 +255,7 @@ export const useMediaControls = ({ ref, handleAction, filenameRef, + visualizationMode, + handleVisualizationModeChange, ]); }; diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/audio.ts b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/audio.ts deleted file mode 100644 index 3105bee..0000000 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/audio.ts +++ /dev/null @@ -1,146 +0,0 @@ -import * as React from 'react'; - -export interface UseAudioControlsOptions { - actionFormKey?: string; - forwardedRef?: React.Ref; -} - -export const useAudioControls = ({ - forwardedRef, - actionFormKey = 'action' as const, -}: UseAudioControlsOptions) => { - const mediaControllerRef = React.useRef(null); - const volumeRef = React.useRef(null); - const filenameRef = React.useRef(null); - const [isPlaying, setIsPlaying] = React.useState(false); - const [isSeeking, setIsSeeking] = React.useState(false); - const [currentTimeDisplay, setCurrentTimeDisplay] = React.useState(); - const [seekTimeDisplay, setSeekTimeDisplay] = React.useState(); - const [durationDisplay, setDurationDisplay] = React.useState(); - const [isSeekTimeCountingDown, setIsSeekTimeCountingDown] = React.useState(false); - - const refreshControls: React.ReactEventHandler = React.useCallback((e) => { - const { currentTarget: mediaController } = e; - - setCurrentTimeDisplay(mediaController.currentTime); - setDurationDisplay(mediaController.duration); - }, []); - - const reset: React.ReactEventHandler = React.useCallback((e) => { - const videoElement = e.currentTarget; - setIsPlaying(false); - videoElement.currentTime = 0; - }, []); - - const updateSeekFromPlayback = React.useCallback((e) => { - if (isSeeking) { - return; - } - - const videoElement = e.currentTarget; - const currentTime = videoElement.currentTime; - setCurrentTimeDisplay(currentTime); - }, [isSeeking]); - - const adjustVolume: React.ChangeEventHandler = React.useCallback((e) => { - if (!(typeof mediaControllerRef === 'object' && mediaControllerRef !== null)) { - return; - } - - if (!mediaControllerRef.current) { - return; - } - const { value } = e.currentTarget; - mediaControllerRef.current.volume = Number(value); - }, [mediaControllerRef]); - - const togglePlayback = React.useCallback(() => { - setIsPlaying((p) => !p); - }, []); - - const toggleSeekTimeCountMode = React.useCallback(() => { - setIsSeekTimeCountingDown((b) => !b); - }, []); - - const download = React.useCallback(() => { - if (!(typeof mediaControllerRef === 'object' && mediaControllerRef?.current !== null)) { - return; - } - - if (!(typeof filenameRef === 'object' && filenameRef?.current !== null)) { - return; - } - - const downloadLink = window.document.createElement('a'); - downloadLink.download = filenameRef.current.textContent ?? 'image'; - downloadLink.href = mediaControllerRef.current.currentSrc; - downloadLink.addEventListener('click', () => { - downloadLink.remove(); - }); - downloadLink.click(); - }, [mediaControllerRef, filenameRef]); - - const actions = React.useMemo(() => ({ - togglePlayback, - toggleSeekTimeCountMode, - download, - }), [togglePlayback, toggleSeekTimeCountMode, download]); - - const handleAction: React.FormEventHandler = React.useCallback((e) => { - e.preventDefault(); - const formData = new FormData(e.currentTarget, (e.nativeEvent as unknown as { submitter: HTMLElement }).submitter); - const actionName = formData.get(actionFormKey) as keyof typeof actions; - const { [actionName]: actionFunction } = actions; - actionFunction?.(); - }, [actions, actionFormKey]); - - React.useEffect(() => { - if (!(typeof mediaControllerRef === 'object' && mediaControllerRef !== null)) { - return; - } - - if (!mediaControllerRef.current) { - return; - } - - if (isPlaying) { - //console.log(mediaControllerRef.current); - void mediaControllerRef.current.play(); - return - } - - mediaControllerRef.current.pause(); - }, [isPlaying, mediaControllerRef]); - - return React.useMemo(() => ({ - mediaControllerRef, - refreshControls, - reset: reset, - updateSeekFromPlayback, - isPlaying, - isSeeking, - currentTimeDisplay, - seekTimeDisplay, - durationDisplay, - isSeekTimeCountingDown, - volumeRef, - adjustVolume, - filenameRef, - handleAction, - }), [ - mediaControllerRef, - refreshControls, - reset, - updateSeekFromPlayback, - isPlaying, - isSeeking, - currentTimeDisplay, - seekTimeDisplay, - durationDisplay, - isSeekTimeCountingDown, - volumeRef, - adjustVolume, - filenameRef, - handleAction, - ]); -}; diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/index.ts b/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/index.ts deleted file mode 100644 index 2dd7daa..0000000 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/hooks/media/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './audio'; -export * from './video'; -export * from './image'; diff --git a/packages/web-kitchensink-reactnext/src/categories/blob/react/index.ts b/packages/web-kitchensink-reactnext/src/categories/blob/react/index.ts index 9a7d03a..fc6ee9b 100644 --- a/packages/web-kitchensink-reactnext/src/categories/blob/react/index.ts +++ b/packages/web-kitchensink-reactnext/src/categories/blob/react/index.ts @@ -7,4 +7,4 @@ export * from './components/ImageFilePreview'; export * from './components/VideoFilePreview'; export * from './hooks/blob'; -export * from './hooks/media'; +export * from './hooks/interactive'; diff --git a/packages/web-kitchensink-reactnext/src/packages/react-wavesurfer/WaveSurferCanvas/index.tsx b/packages/web-kitchensink-reactnext/src/packages/react-wavesurfer/WaveSurferCanvas/index.tsx index 6a81d37..9696555 100644 --- a/packages/web-kitchensink-reactnext/src/packages/react-wavesurfer/WaveSurferCanvas/index.tsx +++ b/packages/web-kitchensink-reactnext/src/packages/react-wavesurfer/WaveSurferCanvas/index.tsx @@ -69,6 +69,7 @@ export const WaveSurferCanvas = React.forwardRef { if (!container) { return; @@ -107,6 +106,8 @@ export const WaveSurferCanvas = React.forwardRef -