After a merge decideEmbedState became the canonical guard and inlines the cycle/too-deep logic, leaving these predicates called only by their own tests. Remove them (and their test blocks); keep PAGE_EMBED_MAX_DEPTH (used by decideEmbedState). Production behavior stays covered by decide-embed-state.test.ts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
import React, { createContext, useContext, useMemo } from "react";
|
|
|
|
/** Hard cap on nesting depth for whole-page embeds (cycle/runaway guard). */
|
|
export const PAGE_EMBED_MAX_DEPTH = 5;
|
|
|
|
type AncestryValue = {
|
|
/** sourcePageIds of every ancestor pageEmbed up the render tree. */
|
|
chain: string[];
|
|
/** Includes the host page id so a top-level self-embed is also caught. */
|
|
hostPageId: string | null;
|
|
};
|
|
|
|
const PageEmbedAncestryContext = createContext<AncestryValue>({
|
|
chain: [],
|
|
hostPageId: null,
|
|
});
|
|
|
|
/**
|
|
* Carries the ancestor `sourcePageId` chain down the nested read-only editors.
|
|
* The node view reads it to detect cycles (current id already in the chain) and
|
|
* to enforce a hard depth limit before mounting a deeper nested editor.
|
|
*/
|
|
export function PageEmbedAncestryProvider({
|
|
sourcePageId,
|
|
hostPageId,
|
|
children,
|
|
}: {
|
|
sourcePageId?: string | null;
|
|
hostPageId?: string | null;
|
|
children: React.ReactNode;
|
|
}) {
|
|
const parent = useContext(PageEmbedAncestryContext);
|
|
const value = useMemo<AncestryValue>(() => {
|
|
const nextHost = parent.hostPageId ?? hostPageId ?? null;
|
|
if (!sourcePageId) {
|
|
return { chain: parent.chain, hostPageId: nextHost };
|
|
}
|
|
return {
|
|
chain: [...parent.chain, sourcePageId],
|
|
hostPageId: nextHost,
|
|
};
|
|
}, [parent, sourcePageId, hostPageId]);
|
|
|
|
return (
|
|
<PageEmbedAncestryContext.Provider value={value}>
|
|
{children}
|
|
</PageEmbedAncestryContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function usePageEmbedAncestry() {
|
|
return useContext(PageEmbedAncestryContext);
|
|
}
|