hydrogen-sanity
Version:
Sanity.io toolkit for Hydrogen
129 lines (125 loc) • 4.04 kB
JavaScript
import { isMaybePresentation } from '@sanity/presentation-comlink';
import { enableVisualEditing } from '@sanity/visual-editing';
import { useRef, useState, useEffect, useMemo } from 'react';
import { useNavigate, useLocation, useSubmit, useRevalidator } from 'react-router';
import { useEffectEvent } from 'use-effect-event';
import { isServer, sanitizePerspective } from './utils.js';
import { useRefresh } from './refresh.js';
import { useHasActiveLoaders } from './registry.js';
function useHistory() {
const navigateRemix = useNavigate();
const navigateRemixRef = useRef(navigateRemix);
const [navigate, setNavigate] = useState();
const location = useLocation();
const isProgrammaticNavRef = useRef(false);
useEffect(() => {
navigateRemixRef.current = navigateRemix;
}, [navigateRemix]);
useEffect(() => {
if (navigate && !isProgrammaticNavRef.current) {
navigate({
type: "push",
url: `${location.pathname}${location.search}${location.hash}`
});
}
isProgrammaticNavRef.current = false;
}, [location.hash, location.pathname, location.search, navigate]);
const historyAdapter = useMemo(
() => ({
subscribe(_navigate) {
setNavigate(() => _navigate);
return () => setNavigate(void 0);
},
update(update) {
isProgrammaticNavRef.current = true;
if (update.type === "push" || update.type === "replace") {
navigateRemixRef.current(update.url, {
replace: update.type === "replace"
});
} else if (update.type === "pop") {
navigateRemixRef.current(-1);
}
}
}),
[]
);
return historyAdapter;
}
if (isServer()) {
throw new Error(
"Overlays should only run client-side. Please check that this file is not being imported into a worker or server bundle."
);
}
function OverlaysClient(props) {
const { components, zIndex, refresh, action = "/api/preview" } = props;
const submit = useSubmit();
const revalidator = useRevalidator();
const { refreshHandler } = useRefresh();
const refreshFn = refreshHandler(refresh);
const historyAdapter = useHistory();
const hasActiveLoaders = useHasActiveLoaders();
const [inStudioContext] = useState(() => {
if (isServer()) {
return null;
}
return isMaybePresentation();
});
const handlePerspectiveChange = useEffectEvent((perspective) => {
const cleanPerspective = sanitizePerspective(perspective);
const formData = new FormData();
formData.set(
"perspective",
Array.isArray(cleanPerspective) ? cleanPerspective.join(",") : cleanPerspective
);
submit(formData, {
method: "PUT",
action,
navigate: false,
preventScrollReset: true
});
refreshFn({
source: "manual",
livePreviewEnabled: false
// Force server revalidation for perspective changes
});
});
const handleRefresh = useEffectEvent((payload) => {
if (refresh) {
return refresh(payload, () => refreshFn(payload), revalidator);
}
switch (payload.source) {
case "manual":
return refreshFn(payload);
default:
if (hasActiveLoaders) {
return false;
}
return refreshFn(payload);
}
});
useEffect(() => {
if (isServer() || !inStudioContext) return void 0;
const handleMessage = (event) => {
const { type, data } = event.data || {};
if (type === "presentation/perspective") {
handlePerspectiveChange(data.perspective);
}
};
window.addEventListener("message", handleMessage);
return () => {
window.removeEventListener("message", handleMessage);
};
}, [inStudioContext]);
useEffect(() => {
const disable = enableVisualEditing({
components,
zIndex,
refresh: handleRefresh,
history: historyAdapter
});
return () => disable();
}, [components, zIndex, historyAdapter]);
return null;
}
export { OverlaysClient as default };
//# sourceMappingURL=Overlays.client.js.map