next-sanity
Version:
Sanity.io toolkit for Next.js
121 lines (120 loc) • 4.46 kB
JavaScript
import { jsx } from "react/jsx-runtime";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { VisualEditing as VisualEditing$1 } from "@sanity/visual-editing/react";
import { revalidateRootLayout } from "next-sanity/visual-editing/server-actions";
function pathHasPrefix(path, prefix) {
if (typeof path !== "string") return false;
const { pathname } = parsePath(path);
return pathname === prefix || pathname.startsWith(`${prefix}/`);
}
function parsePath(path) {
const hashIndex = path.indexOf("#");
const queryIndex = path.indexOf("?");
const hasQuery = queryIndex > -1 && (hashIndex < 0 || queryIndex < hashIndex);
if (hasQuery || hashIndex > -1) return {
pathname: path.substring(0, hasQuery ? queryIndex : hashIndex),
query: hasQuery ? path.substring(queryIndex, hashIndex > -1 ? hashIndex : void 0) : "",
hash: hashIndex > -1 ? path.slice(hashIndex) : ""
};
return {
pathname: path,
query: "",
hash: ""
};
}
function addPathPrefix(path, prefix) {
if (!path.startsWith("/") || !prefix) return path;
if (path === "/" && prefix) return prefix;
const { pathname, query, hash } = parsePath(path);
return `${prefix}${pathname}${query}${hash}`;
}
function removePathPrefix(path, prefix) {
if (!pathHasPrefix(path, prefix)) return path;
const withoutPrefix = path.slice(prefix.length);
if (withoutPrefix.startsWith("/")) return withoutPrefix;
return `/${withoutPrefix}`;
}
const normalizePathTrailingSlash = (path, trailingSlash) => {
const { pathname, query, hash } = parsePath(path);
if (trailingSlash) {
if (pathname.endsWith("/")) return `${pathname}${query}${hash}`;
return `${pathname}/${query}${hash}`;
}
return `${removeTrailingSlash(pathname)}${query}${hash}`;
};
function removeTrailingSlash(route) {
return route.replace(/\/$/, "") || "/";
}
function VisualEditing(props) {
const { basePath = "", plugins, components, refresh, trailingSlash = false, zIndex } = props;
const router = useRouter();
const routerRef = useRef(router);
const [navigate, setNavigate] = useState();
useEffect(() => {
routerRef.current = router;
}, [router]);
const history = useMemo(() => ({
subscribe: (_navigate) => {
setNavigate(() => _navigate);
return () => setNavigate(void 0);
},
update: (update) => {
switch (update.type) {
case "push": return routerRef.current.push(removePathPrefix(update.url, basePath));
case "pop": return routerRef.current.back();
case "replace": return routerRef.current.replace(removePathPrefix(update.url, basePath));
default: throw new Error(`Unknown update type: ${update.type}`);
}
}
}), [basePath]);
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
if (navigate) navigate({
type: "push",
url: normalizePathTrailingSlash(addPathPrefix(`${pathname}${searchParams?.size ? `?${searchParams}` : ""}`, basePath), trailingSlash)
});
}, [
basePath,
navigate,
pathname,
searchParams,
trailingSlash
]);
const handleRefresh = useCallback((payload) => {
if (refresh) return refresh(payload);
const manualFastRefresh = () => {
console.debug("Live preview is setup, calling router.refresh() to refresh the server components without refetching cached data");
routerRef.current.refresh();
return Promise.resolve();
};
const manualFallbackRefresh = () => {
console.debug("No loaders in live mode detected, or preview kit setup, revalidating root layout");
return revalidateRootLayout();
};
const mutationFallbackRefresh = () => {
console.debug("No loaders in live mode detected, or preview kit setup, revalidating root layout");
return revalidateRootLayout();
};
switch (payload.source) {
case "manual": return payload.livePreviewEnabled ? manualFastRefresh() : manualFallbackRefresh();
case "mutation": return payload.livePreviewEnabled ? mutationFastRefresh() : mutationFallbackRefresh();
default: throw new Error("Unknown refresh source", { cause: payload });
}
}, [refresh]);
return /* @__PURE__ */ jsx(VisualEditing$1, {
plugins,
components,
history,
portal: true,
refresh: handleRefresh,
zIndex
});
}
function mutationFastRefresh() {
console.debug("Live preview is setup, mutation is skipped assuming its handled by the live preview");
return false;
}
export { VisualEditing as default };
//# sourceMappingURL=VisualEditing.js.map