Files
medusa-store/www/reference/src/context/navigation-context.js
2022-04-05 11:22:25 +02:00

184 lines
4.1 KiB
JavaScript

import React, { useReducer } from "react"
import { checkDisplay } from "../utils/check-display"
import scrollParent from "../utils/scroll-parent"
import types from "./types"
export const defaultNavigationContext = {
api: "null",
setApi: () => {},
currentSection: null,
currentSectionObj: {
section_name: "",
paths: [],
schema: {}
},
updateSection: () => {},
currentHash: null,
updateHash: () => {},
openSections: [],
openSection: () => {},
metadata: null,
updateMetadata: () => {},
reset: () => {},
}
const NavigationContext = React.createContext(defaultNavigationContext)
export default NavigationContext
const reducer = (state, action) => {
let obj = []
switch (action.type) {
case types.SET_API: {
return {
...state,
api: action.payload,
}
}
case types.UPDATE_HASH:
obj.push(action.payload.section)
return {
...state,
openSections: obj,
currentSection: action.payload.section,
currentHash: action.payload.method,
currentSectionObj: action.payload.sectionObj
}
case types.UPDATE_SECTION:
obj.push(action.payload.id)
return {
...state,
openSections: obj,
currentSection: action.payload.id,
currentHash: null,
currentSectionObj: action.payload.section
}
case types.OPEN_SECTION:
obj.push(action.payload.id)
return {
...state,
openSections: obj,
currentSection: action.payload.id,
currentSectionObj: action.payload.section
}
case types.RESET:
return {
...state,
openSections: [],
currentSection: null,
currentHash: null,
currentSectionObj: {
section_name: "",
paths: [],
schema: {}
}
}
case types.UPDATE_METADATA:
return {
...state,
metadata: {
title: action.payload.title,
description: action.payload.description,
},
}
default:
return state
}
}
const scrollNav = id => {
const nav = document.querySelector("#nav")
if (nav) {
const element = nav.querySelector(`#nav-${id}`)
if (element) {
scrollParent(nav, element)
}
}
}
const scrollToElement = async id => {
const element = document.querySelector(`#${id}`)
if (element) {
if (checkDisplay(element)) {
element.scrollIntoView({
block: "start",
inline: "nearest",
})
} else {
setTimeout(() => {
scrollToElement(id)
}, 100)
}
} else {
setTimeout(() => {
scrollToElement(id)
}, 100)
}
}
export const NavigationProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, defaultNavigationContext)
const setApi = api => {
dispatch({ type: types.SET_API, payload: api })
}
const updateMetadata = metadata => {
dispatch({ type: types.UPDATE_METADATA, payload: metadata })
}
const updateHash = (section, method, sectionObj) => {
dispatch({
type: types.UPDATE_HASH,
payload: { method: method, section: section, sectionObj },
})
window.history.replaceState(
null,
"",
`/api/${state.api}/${section}/${method}`
)
scrollNav(method)
}
const updateSection = ({id, section}) => {
dispatch({ type: types.UPDATE_SECTION, payload: {id, section} })
window.history.replaceState(null, "", `/api/${state.api}/${id}`)
scrollNav(id)
}
const openSection = ({id, section}) => {
dispatch({ type: types.OPEN_SECTION, payload: {id, section} })
}
const goTo = to => {
const { section, method, sectionObj } = to
if (!state.openSections.includes(section)) {
openSection({id: section, section: sectionObj})
}
scrollToElement(method || section)
}
const reset = () => {
dispatch({ type: types.RESET })
}
return (
<NavigationContext.Provider
value={{
...state,
openSection,
updateSection,
updateHash,
setApi,
goTo,
reset,
updateMetadata,
dispatch,
}}
>
{children}
</NavigationContext.Provider>
)
}