Skip to content

Commit 8c382c5

Browse files
Feat(unitex): Add go to previous / go to next support
1 parent bb4a11b commit 8c382c5

7 files changed

Lines changed: 124 additions & 10 deletions

File tree

packages/react-tei/src/SidePanel/unitex/UnitexAnnotation.spec.tsx

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import { describe, expect, it, vi } from "vitest";
22
import { render } from "vitest-browser-react";
33
import { I18nProvider } from "../../i18n/I18nProvider";
4+
import type { DocumentNavigationContextValue } from "../../navigation/DocumentNavigationContext";
5+
import { TestDocumentNavigationContextProvider } from "../../navigation/TestDocumentNavigationContextProvider";
46
import { UnitexAnnotation } from "./UnitexAnnotation";
57

6-
vi.mock("../../DocumentContextProvider");
7-
8-
function TestWrapper({ children }: { children: React.ReactNode }) {
9-
return <I18nProvider>{children}</I18nProvider>;
8+
function TestWrapper({
9+
navigateToBodyTargetSelector,
10+
children,
11+
}: {
12+
navigateToBodyTargetSelector?: DocumentNavigationContextValue["navigateToBodyTargetSelector"];
13+
children: React.ReactNode;
14+
}) {
15+
return (
16+
<TestDocumentNavigationContextProvider
17+
value={{
18+
navigateToBodyTargetSelector,
19+
}}
20+
>
21+
<I18nProvider>{children}</I18nProvider>
22+
</TestDocumentNavigationContextProvider>
23+
);
1024
}
1125

1226
describe("UnitexAnnotation", () => {
@@ -48,4 +62,69 @@ describe("UnitexAnnotation", () => {
4862

4963
expect(onToggle).toHaveBeenCalledTimes(1);
5064
});
65+
66+
it("should disable navigation buttons when annotation is not displayed", async () => {
67+
const screen = await render(
68+
<UnitexAnnotation
69+
annotation={{ term: "example", frequency: 5, displayed: false }}
70+
color="blue"
71+
onToggle={() => {}}
72+
/>,
73+
{
74+
wrapper: TestWrapper,
75+
},
76+
);
77+
78+
const previousButton = screen.getByRole("button", {
79+
name: "Aller au précédent",
80+
});
81+
const nextButton = screen.getByRole("button", {
82+
name: "Aller au suivant",
83+
});
84+
85+
await expect.element(previousButton).toBeDisabled();
86+
await expect.element(nextButton).toBeDisabled();
87+
});
88+
89+
it("should call navigateToBodyTargetSelector when navigation buttons are clicked", async () => {
90+
const navigateToBodyTargetSelector = vi.fn();
91+
const screen = await render(
92+
<UnitexAnnotation
93+
annotation={{ term: "example", frequency: 5, displayed: true }}
94+
color="blue"
95+
onToggle={() => {}}
96+
/>,
97+
{
98+
wrapper: ({ children }) => (
99+
<TestWrapper
100+
navigateToBodyTargetSelector={navigateToBodyTargetSelector}
101+
>
102+
{children}
103+
</TestWrapper>
104+
),
105+
},
106+
);
107+
108+
const previousButton = screen.getByRole("button", {
109+
name: "Aller au précédent",
110+
});
111+
const nextButton = screen.getByRole("button", {
112+
name: "Aller au suivant",
113+
});
114+
115+
await expect.element(previousButton).toBeEnabled();
116+
await expect.element(nextButton).toBeEnabled();
117+
118+
await previousButton.click();
119+
expect(navigateToBodyTargetSelector).toHaveBeenCalledWith(
120+
"[data-term=example]",
121+
-1,
122+
);
123+
124+
await nextButton.click();
125+
expect(navigateToBodyTargetSelector).toHaveBeenCalledWith(
126+
"[data-term=example]",
127+
1,
128+
);
129+
});
51130
});

packages/react-tei/src/SidePanel/unitex/UnitexAnnotation.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import IconButton from "@mui/material/IconButton";
88
import Stack from "@mui/material/Stack";
99
import Tooltip from "@mui/material/Tooltip";
1010
import { useTranslation } from "react-i18next";
11+
import { kebabCasify } from "../../helper/kebabCasify";
12+
import { useDocumentNavigation } from "../../navigation/useNavigateToSection";
1113
import type { TermStatistic } from "../../unitex/parseUnitexEnrichment";
1214

1315
export function UnitexAnnotation({
@@ -16,12 +18,23 @@ export function UnitexAnnotation({
1618
onToggle,
1719
}: UnitexAnnotationProps) {
1820
const { t } = useTranslation();
21+
const { navigateToBodyTargetSelector } = useDocumentNavigation();
1922

2023
const checkBoxLabel = t("unitex.toggleTerm", {
2124
context: annotation.displayed ? "hide" : "show",
2225
term: annotation.term,
2326
});
2427

28+
const selector = `[data-term=${kebabCasify(annotation.term)}]`;
29+
30+
const handleGoToPrevious = () => {
31+
navigateToBodyTargetSelector(selector, -1);
32+
};
33+
34+
const handleGoToNext = () => {
35+
navigateToBodyTargetSelector(selector, 1);
36+
};
37+
2538
return (
2639
<>
2740
<Tooltip title={checkBoxLabel} placement="left">
@@ -70,10 +83,20 @@ export function UnitexAnnotation({
7083
</Tooltip>
7184
</Box>
7285
<Stack gap={0.5} direction="row">
73-
<IconButton size="small" disabled={!annotation.displayed}>
86+
<IconButton
87+
size="small"
88+
disabled={!annotation.displayed}
89+
onClick={handleGoToPrevious}
90+
aria-label={t("unitex.previous")}
91+
>
7492
<ArrowUpIcon />
7593
</IconButton>
76-
<IconButton size="small" disabled={!annotation.displayed}>
94+
<IconButton
95+
size="small"
96+
disabled={!annotation.displayed}
97+
onClick={handleGoToNext}
98+
aria-label={t("unitex.next")}
99+
>
77100
<ArrowDownIcon />
78101
</IconButton>
79102
</Stack>

packages/react-tei/src/SidePanel/unitex/UnitexAnnotationBlock.spec.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { render } from "vitest-browser-react";
33

44
import { DocumentContextProvider } from "../../DocumentContextProvider";
55
import { I18nProvider } from "../../i18n/I18nProvider";
6+
import { TestDocumentNavigationContextProvider } from "../../navigation/TestDocumentNavigationContextProvider";
67
import type { TermStatistic } from "../../unitex/parseUnitexEnrichment";
78
import { UnitexAnnotationBlock } from "./UnitexAnnotationBlock";
89
import type { UnitexAnnotationBlockType } from "./unitexAnnotationBlocks";
@@ -22,7 +23,9 @@ function TestWrapper({ children }: { children: React.ReactNode }) {
2223
jsonDocument={[]}
2324
jsonUnitexEnrichment={enrichments}
2425
>
25-
{children}
26+
<TestDocumentNavigationContextProvider>
27+
{children}
28+
</TestDocumentNavigationContextProvider>
2629
</DocumentContextProvider>
2730
</I18nProvider>
2831
);

packages/react-tei/src/SidePanel/unitex/UnitexSection.spec.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { render } from "vitest-browser-react";
33

44
import { DocumentContextProvider } from "../../DocumentContextProvider";
55
import { I18nProvider } from "../../i18n/I18nProvider";
6+
import { TestDocumentNavigationContextProvider } from "../../navigation/TestDocumentNavigationContextProvider";
67
import type { TermStatistic } from "../../unitex/parseUnitexEnrichment";
78
import { UnitexSection } from "./UnitexSection";
89
import type { UnitexAnnotationBlockType } from "./unitexAnnotationBlocks";
@@ -22,7 +23,9 @@ function TestWrapper({ children }: { children: React.ReactNode }) {
2223
jsonDocument={[]}
2324
jsonUnitexEnrichment={enrichments}
2425
>
25-
{children}
26+
<TestDocumentNavigationContextProvider>
27+
{children}
28+
</TestDocumentNavigationContextProvider>
2629
</DocumentContextProvider>
2730
</I18nProvider>
2831
);

packages/react-tei/src/i18n/locales/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export const en: Translation = {
4949
toggleBlock_hide: "Deactivate underlining of words in the text",
5050
toggleTerm_show: 'Activate underlining for the term "{{term}}"',
5151
toggleTerm_hide: 'Deactivate underlining for the term "{{term}}"',
52+
previous: "Go to previous",
53+
next: "Go to next",
5254

5355
date_one: "Date ({{count}})",
5456
date_other: "Dates ({{count}})",

packages/react-tei/src/i18n/locales/fr.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export const fr = {
4747
toggleBlock_hide: "Désactiver le soulignement des mots dans le texte",
4848
toggleTerm_show: 'Activer le soulignement pour le terme "{{term}}"',
4949
toggleTerm_hide: 'Désactiver le soulignement pour le terme "{{term}}"',
50+
previous: "Aller au précédent",
51+
next: "Aller au suivant",
5052

5153
date_one: "Date ({{count}})",
5254
date_other: "Dates ({{count}})",

packages/react-tei/src/navigation/DocumentNavigationContext.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createContext, useCallback, useEffect, useMemo, useRef } from "react";
22
import { useDocumentContext } from "../DocumentContextProvider";
33

44
export type DocumentNavigationContextValue = {
5-
navigateToBodyTargetSelector(querySelector: string): void;
5+
navigateToBodyTargetSelector(querySelector: string, order?: number): void;
66
navigateToHeading(headingId: string): void;
77
navigateToFootnote(footnoteId: string): void;
88
navigateToFootnoteRef(id: string): void;
@@ -111,7 +111,9 @@ export function DocumentNavigationContextProvider({
111111
};
112112
} else {
113113
currentSelectorRef.current.index =
114-
(currentSelectorRef.current.index + direction) %
114+
(currentSelectorRef.current.index +
115+
direction +
116+
targetElements.length) %
115117
targetElements.length;
116118
}
117119

0 commit comments

Comments
 (0)