Skip to content

Commit 18255b8

Browse files
authored
Merge pull request #41 from BKWLD/fix-next-app-router
Fix next app router support
2 parents f92f5ea + b583c30 commit 18255b8

4 files changed

Lines changed: 85 additions & 40 deletions

File tree

packages/react/src/LazyVideo.tsx renamed to packages/react/src/LazyVideo/LazyVideoClient.tsx

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,28 @@
44
import { useInView } from 'react-intersection-observer'
55
import { useMediaQueries } from '@react-hook/media-query'
66
import { useEffect, type ReactElement, useRef, useCallback, type MutableRefObject } from 'react'
7-
import type { LazyVideoProps } from './types/lazyVideoTypes';
8-
import { fillStyles, transparentGif } from './lib/styles'
7+
import type { LazyVideoProps } from '../types/lazyVideoTypes';
8+
import { fillStyles, transparentGif } from '../lib/styles'
99

10-
type VideoSourceProps = {
11-
src: Required<LazyVideoProps>['src']
12-
videoLoader: LazyVideoProps['videoLoader']
10+
type LazyVideoClientProps = Omit<LazyVideoProps,
11+
'videoLoader' | 'src' | 'sourceMedia'
12+
> & {
13+
srcUrl?: string
14+
mediaSrcs?: Record<string, string>
1315
}
1416

15-
type ResponsiveVideoSourceProps = Pick<Required<LazyVideoProps>,
16-
'src' | 'videoLoader' | 'sourceMedia'
17-
> & {
17+
type ResponsiveVideoSourceProps = {
18+
mediaSrcs: Required<LazyVideoClientProps>['mediaSrcs']
1819
videoRef: VideoRef
1920
}
2021

2122
type VideoRef = MutableRefObject<HTMLVideoElement | undefined>
2223

2324
// An video rendered within a Visual that supports lazy loading
24-
export default function LazyVideo({
25-
src, sourceMedia, videoLoader,
25+
export default function LazyVideoClient({
26+
srcUrl, mediaSrcs,
2627
alt, fit, position, priority, noPoster, paused,
27-
}: LazyVideoProps): ReactElement {
28+
}: LazyVideoClientProps): ReactElement {
2829

2930
// Make a ref to the video so it can be controlled
3031
const videoRef = useRef<HTMLVideoElement>()
@@ -67,11 +68,6 @@ export default function LazyVideo({
6768
// Simplify logic for whether to load sources
6869
const shouldLoad = priority || inView
6970

70-
// Multiple media queries and a loader func are necessary for responsive
71-
const useResponsiveSource = sourceMedia
72-
&& sourceMedia?.length > 1
73-
&& !!videoLoader
74-
7571
// Render video tag
7672
return (
7773
<video
@@ -100,39 +96,21 @@ export default function LazyVideo({
10096
}}>
10197

10298
{/* Implement lazy loading by not adding the source until ready */}
103-
{ shouldLoad && (useResponsiveSource ?
104-
<ResponsiveSource { ...{ src, videoLoader, sourceMedia, videoRef }} /> :
105-
<Source {...{ src, videoLoader }} />
99+
{ shouldLoad && (mediaSrcs ?
100+
<ResponsiveSource { ...{ mediaSrcs, videoRef }} /> :
101+
<source src={ srcUrl } type='video/mp4' />
106102
)}
107103
</video>
108104
)
109105
}
110106

111-
// Return a simple source element
112-
function Source({
113-
src, videoLoader
114-
}: VideoSourceProps): ReactElement | undefined {
115-
let srcUrl
116-
if (videoLoader) srcUrl = videoLoader({ src })
117-
else if (typeof src == 'string') srcUrl = src
118-
if (!srcUrl) return
119-
return (<source src={ srcUrl } type='video/mp4' />)
120-
}
121-
122107
// Switch the video asset depending on media queries
123108
function ResponsiveSource({
124-
src, videoLoader, sourceMedia, videoRef
109+
mediaSrcs, videoRef
125110
}: ResponsiveVideoSourceProps): ReactElement | undefined {
126111

127-
// Prepare a hash of source URLs and their media query constraint in the
128-
// style expected by useMediaQueries
129-
const queries = Object.fromEntries(sourceMedia.map(media => {
130-
const url = videoLoader({ src, media })
131-
return [url, media]
132-
}))
133-
134112
// Find the src url that is currently active
135-
const { matches } = useMediaQueries(queries)
113+
const { matches } = useMediaQueries(mediaSrcs)
136114
const srcUrl = getFirstMatch(matches)
137115

138116
// Reload the video since the source changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type { ReactElement } from 'react'
2+
import type { LazyVideoProps } from '../types/lazyVideoTypes'
3+
import LazyVideoClient from './LazyVideoClient'
4+
5+
// This wrapper function exists to take Function props and make them
6+
// serializable for the LazyVideoClient component, which is a Next.js style
7+
// client component.
8+
export default function LazyVideo(
9+
props: LazyVideoProps
10+
): ReactElement | undefined {
11+
12+
// Destructure some props
13+
const {
14+
src,
15+
sourceMedia,
16+
videoLoader,
17+
} = props
18+
19+
// Multiple media queries and a loader func are necessary for responsive
20+
const useResponsiveSource = sourceMedia
21+
&& sourceMedia?.length > 1
22+
&& !!videoLoader
23+
24+
// Vars that will be conditionally populated
25+
let srcUrl, mediaSrcs
26+
27+
// Prepare a hash of source URLs and their media query constraint in the
28+
// style expected by useMediaQueries.
29+
if (useResponsiveSource) {
30+
const mediaSrcEntries = sourceMedia.map(media => {
31+
const url = videoLoader({ src, media })
32+
return [url, media]
33+
})
34+
// If the array ended up empty, abort
35+
if (mediaSrcEntries.filter(([url]) => !!url).length == 0) return
36+
37+
// Make the hash
38+
mediaSrcs = Object.fromEntries(mediaSrcEntries)
39+
40+
// Make a simple string src url
41+
} else {
42+
if (videoLoader) srcUrl = videoLoader({ src })
43+
else if (typeof src == 'string') srcUrl = src
44+
if (!srcUrl) return // If no url could be built, abort
45+
}
46+
47+
// Render client component
48+
return (
49+
<LazyVideoClient {...{
50+
...props,
51+
52+
// Remove client-unfriendly props
53+
videoLoader: undefined,
54+
src: undefined,
55+
sourceMedia: undefined,
56+
57+
// Add client-friendly props
58+
srcUrl,
59+
mediaSrcs,
60+
}}
61+
/>
62+
)
63+
}
64+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Export the server component as the defalut LazyVideo component
2+
import LazyVideoServer from './LazyVideoServer'
3+
export default LazyVideoServer

packages/react/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import ReactVisual from './ReactVisual'
2-
import LazyVideo from './LazyVideo'
2+
import LazyVideo from './LazyVideo/LazyVideoServer'
33
import VisualWrapper from './VisualWrapper'
44
import { collectDataAttributes } from './lib/attributes'
55

0 commit comments

Comments
 (0)