Skip to content

Commit 505d661

Browse files
committed
enhance(carousel): Close carousel on browser back navigation
1 parent 6179ffb commit 505d661

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

components/carousel.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,31 @@ function CarouselOverflow ({ originalSrc, rel }) {
114114
export function CarouselProvider ({ children }) {
115115
const media = useRef(new Map())
116116
const showModal = useShowModal()
117+
const isCarouselOpenRef = useRef(false)
118+
const isOpeningCarouselRef = useRef(false)
119+
120+
// Helper function to get confirmed entries
121+
const getConfirmedEntries = useCallback(() => {
122+
return Array.from(media.current.entries())
123+
.filter(([, entry]) => entry.confirmed)
124+
}, [])
117125

118126
const showCarousel = useCallback(({ src }) => {
119127
// only show confirmed entries
120-
const confirmedEntries = Array.from(media.current.entries())
121-
.filter(([, entry]) => entry.confirmed)
128+
const confirmedEntries = getConfirmedEntries()
122129

130+
isCarouselOpenRef.current = true
131+
isOpeningCarouselRef.current = false
123132
showModal((close, setOptions) => {
124133
return <Carousel close={close} mediaArr={confirmedEntries} src={src} setOptions={setOptions} />
125134
}, {
126135
fullScreen: true,
127-
overflow: <CarouselOverflow {...media.current.get(src)} />
136+
overflow: <CarouselOverflow {...media.current.get(src)} />,
137+
hash: 'carousel',
138+
onClose: () => {
139+
isCarouselOpenRef.current = false
140+
isOpeningCarouselRef.current = false
141+
}
128142
})
129143
}, [showModal])
130144

@@ -137,8 +151,18 @@ export function CarouselProvider ({ children }) {
137151
if (mediaItem) {
138152
mediaItem.confirmed = true
139153
media.current.set(src, mediaItem)
154+
155+
if (typeof window !== 'undefined' && window.location.hash === '#carousel' && !isCarouselOpenRef.current) {
156+
if (!isOpeningCarouselRef.current) {
157+
const confirmedEntries = getConfirmedEntries()
158+
if (confirmedEntries.length >= 1) {
159+
isOpeningCarouselRef.current = true
160+
showCarousel({ src })
161+
}
162+
}
163+
}
140164
}
141-
}, [])
165+
}, [showCarousel])
142166

143167
const removeMedia = useCallback((src) => {
144168
media.current.delete(src)

components/modal.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,22 @@ export default function useModal () {
5959
return
6060
}
6161

62+
const currentHash = window.location.hash
63+
if (currentHash) {
64+
const hasModalWithHash = modalStack.current.some(
65+
modal => modal.options?.hash && `#${modal.options.hash}` === currentHash
66+
)
67+
if (hasModalWithHash) {
68+
window.history.replaceState(window.history.state, '', window.location.pathname + window.location.search)
69+
}
70+
}
71+
6272
while (modalStack.current.length) {
6373
getCurrentContent()?.options?.onClose?.()
6474
modalStack.current.pop()
6575
}
6676
forceUpdate()
67-
}, [onBack])
77+
}, [onBack, getCurrentContent])
6878

6979
const router = useRouter()
7080
useEffect(() => {
@@ -80,6 +90,21 @@ export default function useModal () {
8090
return () => router.events.off('routeChangeStart', maybeOnClose)
8191
}, [router.events, onClose, getCurrentContent])
8292

93+
useEffect(() => {
94+
const handleHashChange = () => {
95+
const currentContent = getCurrentContent()
96+
if (!currentContent?.options?.hash) return
97+
98+
const expectedHash = `#${currentContent.options.hash}`
99+
if (window.location.hash !== expectedHash) {
100+
onClose()
101+
}
102+
}
103+
104+
window.addEventListener('hashchange', handleHashChange)
105+
return () => window.removeEventListener('hashchange', handleHashChange)
106+
}, [onClose, getCurrentContent])
107+
83108
const modal = useMemo(() => {
84109
if (modalStack.current.length === 0) {
85110
return null
@@ -116,6 +141,12 @@ export default function useModal () {
116141
const showModal = useCallback(
117142
(getContent, options) => {
118143
document.activeElement?.blur()
144+
if (options?.hash) {
145+
const newHash = `#${options.hash}`
146+
if (window.location.hash !== newHash) {
147+
window.history.pushState(window.history.state, '', newHash)
148+
}
149+
}
119150
const ref = { node: getContent(onClose, setOptions), options }
120151
if (options?.replaceModal) {
121152
modalStack.current = [ref]
@@ -124,7 +155,7 @@ export default function useModal () {
124155
}
125156
forceUpdate()
126157
},
127-
[onClose]
158+
[onClose, setOptions]
128159
)
129160

130161
return [modal, showModal]

0 commit comments

Comments
 (0)