Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,96 @@ describe("DocumentNavigationContextProvider", () => {
);
expect(scrollIntoView).toHaveBeenCalled();
});

it("should open the side panel if it is closed when navigating to a footnote", async () => {
const toggleSection = vi.fn();
const togglePanel = vi.fn();
const { sidePaneElement, wrapper } = createSidePaneWrapper({
state: {
isOpen: false,
sections: {
footnotes: true,
authors: false,
keywords: false,
source: false,
},
},
toggleSection,
togglePanel,
});
const scrollIntoView = vi.fn();
const querySelectorAll = vi.fn().mockImplementation(() => {
const span = document.createElement("span");
span.scrollIntoView = scrollIntoView;

return [span];
});

vi.spyOn(sidePaneElement, "querySelectorAll").mockImplementation(
querySelectorAll,
);
const { result } = await renderHook(() => useDocumentNavigation(), {
wrapper,
});

act(() => {
result.current.navigateToFootnote("footnote-1");
});
expect(togglePanel).toHaveBeenCalled();
expect(querySelectorAll).not.toHaveBeenCalled();
expect(scrollIntoView).not.toHaveBeenCalled();
await new Promise((r) => setTimeout(r, 700)); // wait for the panel and section animation
expect(querySelectorAll).toHaveBeenCalledWith(
'[data-fn-id~="footnote-1"]',
);
expect(scrollIntoView).toHaveBeenCalled();
});

it('should open the side panel and the "footnotes" section if both are closed when navigating to a footnote', async () => {
const toggleSection = vi.fn();
const togglePanel = vi.fn();
const { sidePaneElement, wrapper } = createSidePaneWrapper({
state: {
isOpen: false,
sections: {
footnotes: false,
authors: false,
keywords: false,
source: false,
},
},
toggleSection,
togglePanel,
});
const scrollIntoView = vi.fn();
const querySelectorAll = vi.fn().mockImplementation(() => {
const span = document.createElement("span");
span.scrollIntoView = scrollIntoView;

return [span];
});

vi.spyOn(sidePaneElement, "querySelectorAll").mockImplementation(
querySelectorAll,
);
const { result } = await renderHook(() => useDocumentNavigation(), {
wrapper,
});

act(() => {
result.current.navigateToFootnote("footnote-1");
});
// toggleSection will open both the panel and the section
expect(toggleSection).toHaveBeenCalledWith("footnotes");
expect(togglePanel).not.toHaveBeenCalled();
expect(querySelectorAll).not.toHaveBeenCalled();
expect(scrollIntoView).not.toHaveBeenCalled();
await new Promise((r) => setTimeout(r, 1000)); // wait for the panel and section animation
expect(querySelectorAll).toHaveBeenCalledWith(
'[data-fn-id~="footnote-1"]',
);
expect(scrollIntoView).toHaveBeenCalled();
});
});

describe("navigateToBibliographicReferenceRef", () => {
Expand Down
49 changes: 21 additions & 28 deletions packages/react-tei/src/navigation/DocumentNavigationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { createContext, useCallback, useEffect, useMemo, useRef } from "react";
import { useDocumentContext } from "../DocumentContextProvider";
import {
type PanelSection,
useDocumentContext,
} from "../DocumentContextProvider";

export const DIRECTION_NEXT = "next";
export const DIRECTION_PREVIOUS = "previous";
Expand Down Expand Up @@ -169,52 +172,42 @@ export function DocumentNavigationContextProvider({
);

const navigateToPanelTargetSelector = useCallback(
(querySelector: string) => {
async (section: PanelSection, querySelector: string) => {
const sidePanelElement = sidePanelRef.current;

if (!sidePanelElement) {
console.error("Side panel element not found");
return;
}

if (!panel.state.sections[section]) {
panel.toggleSection(section);
await new Promise((resolve) => setTimeout(resolve, 300));
} else if (!panel.state.isOpen) {
panel.togglePanel();
await new Promise((resolve) => setTimeout(resolve, 300));
}
Comment thread
jonathanarnault marked this conversation as resolved.

navigateToTargetLoop(sidePanelElement, querySelector);
},
[sidePanelRef, navigateToTargetLoop],
[sidePanelRef, navigateToTargetLoop, panel],
);

const navigateToFootnote = useCallback(
(n: string) => {
const selector = buildDataSelector(n, "fn");

if (!panel.state.isOpen || !panel.state.sections.footnotes) {
panel.toggleSection("footnotes");
setTimeout(() => {
navigateToPanelTargetSelector(selector);
}, 600);
return;
}
return navigateToPanelTargetSelector(selector);
navigateToPanelTargetSelector("footnotes", buildDataSelector(n, "fn"));
},
[navigateToPanelTargetSelector, panel],
[navigateToPanelTargetSelector],
);

const navigateToBibliographicReference = useCallback(
(id: string) => {
const selector = buildDataSelector(id, "bibref");

if (
!panel.state.isOpen ||
!panel.state.sections.bibliographicReferences
) {
panel.toggleSection("bibliographicReferences");
setTimeout(() => {
navigateToPanelTargetSelector(selector);
}, 600);
return;
}
return navigateToPanelTargetSelector(selector);
return navigateToPanelTargetSelector(
"bibliographicReferences",
buildDataSelector(id, "bibref"),
);
},
[navigateToPanelTargetSelector, panel],
[navigateToPanelTargetSelector],
);

const navigateToFootnoteRef = useCallback(
Expand Down