Skip to content

Commit

Permalink
feat(contributions): ajout du support des infographies dans les contr…
Browse files Browse the repository at this point in the history
…ibutions
  • Loading branch information
m-maillot committed Feb 6, 2025
1 parent 397232c commit 82a704b
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/code-du-travail-frontend/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "./globals.css";
import 'react-image-lightbox/style.css';
import { Metadata } from "next/types";
import { SITE_URL } from "../src/config";
import { headers } from "next/headers";
Expand Down
9 changes: 8 additions & 1 deletion packages/code-du-travail-frontend/src/lib/xss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ const whiteListTags = ["webcomponent-tooltip", "webcomponent-tooltip-cc"];
* @type {string[]}
* class is used for modeles-de-courrier
*/
const whiteListAttr = ["class", "rel", "href", "target"];
const whiteListAttr = [
"class",
"rel",
"href",
"target",
"data-pdf",
"data-pdf-size",
];

export const xssWrapper = (text: string): string => {
return xss(text, {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useState } from "react";
import Lightbox from "react-image-lightbox";

import { css } from "@styled-system/css";
import useScrollBlock from "../utils/useScrollBlock";

type Props = {
altText: string;
src: string;
};

const InfographicWrapper = ({ altText, src }: Props): JSX.Element => {
const [isOpen, setIsOpen] = useState(false);
const [blockScroll, allowScroll] = useScrollBlock();

const onOpen = () => {
setIsOpen(true);
blockScroll();
};

const onClose = () => {
setIsOpen(false);
allowScroll();
};

return (
<>
<img
src={src}
alt={altText}
onClick={onOpen}
aria-hidden="true"
className={`${ImageZoom}`}
/>
{isOpen && <Lightbox mainSrc={src} onCloseRequest={onClose} />}
</>
);
};

const ImageZoom = css({
cursor: "zoom-in",
});

export default InfographicWrapper;
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import parse, {
HTMLReactParserOptions,
Text,
} from "html-react-parser";
import { xssWrapper } from "../../lib";
import { toUrl, xssWrapper } from "../../lib";
import Alert from "@codegouvfr/react-dsfr/Alert";
import { ElementType } from "react";
import { AccordionWithAnchor } from "../common/AccordionWithAnchor";
import { v4 as generateUUID } from "uuid";
import { fr } from "@codegouvfr/react-dsfr";
import { FicheServicePublic } from "../fiche-service-public/builder";
import ImageWrapper from "../common/ImageWrapper";
import { Tile } from "@codegouvfr/react-dsfr/Tile";

const DEFAULT_HEADING_LEVEL = 3;
export type numberLevel = 2 | 3 | 4 | 5 | 6;
Expand Down Expand Up @@ -257,6 +259,35 @@ const options = (titleLevel: numberLevel): HTMLReactParserOptions => {
></Alert>
);
}
if (domNode.name === "div" && domNode.attribs.class === "infographic") {
const pdfUrl = domNode.attribs["data-pdf"];
const pdfSize = domNode.attribs["data-pdf-size"];
const firstNode = domNode.children.shift();
const pictoUrl =
firstNode?.type === "tag" ? firstNode.attribs.src : "";
return (
<div>
<ImageWrapper altText={""} src={pictoUrl} />
{domToReact(
domNode.children as DOMNode[],
options(titleLevel as numberLevel)
)}
<Tile
downloadButton
enlargeLinkOrButton
imageSvg={false}
imageUrl={`/static/assets/img/modeles-de-courriers-download.svg`}
title={`Télécharger l'infographie`}
titleAs={`h${titleLevel}`}
detail={`Format PDF - ${pdfSize}Ko`}
imageAlt={""}
linkProps={{
href: toUrl(pdfUrl),
}}
/>
</div>
);
}
if (domNode.name === "strong") {
// Disable trim on strong
return <strong>{renderChildrenWithNoTrim(domNode)}</strong>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useRef } from "react";

const safeDocument: any = typeof document !== "undefined" ? document : {};

/**
* Usage:
* const [blockScroll, allowScroll] = useScrollBlock();
*/
const useScrollBlock = (): [() => void, () => void] => {
const scrollBlocked = useRef(false);
const html = safeDocument.documentElement;
const { body } = safeDocument;

const blockScroll = (): void => {
if (!body || !body.style || scrollBlocked.current) return;
if (document == undefined) return;

const scrollBarWidth = window.innerWidth - html.clientWidth;
const bodyPaddingRight =
parseInt(
window.getComputedStyle(body).getPropertyValue("padding-right")
) || 0;

/**
* 1. Fixes a bug in iOS and desktop Safari whereby setting
* `overflow: hidden` on the html/body does not prevent scrolling.
* 2. Fixes a bug in desktop Safari where `overflowY` does not prevent
* scroll if an `overflow-x` style is also applied to the body.
*/
html.style.position = "relative"; /* [1] */
html.style.overflow = "hidden"; /* [2] */
body.style.position = "relative"; /* [1] */
body.style.overflow = "hidden"; /* [2] */
body.style.paddingRight = `${bodyPaddingRight + scrollBarWidth}px`;

scrollBlocked.current = true;
};

const allowScroll = (): void => {
if (!body || !body.style || !scrollBlocked.current) return;

html.style.position = "";
html.style.overflow = "";
body.style.position = "";
body.style.overflow = "";
body.style.paddingRight = "";

scrollBlocked.current = false;
};

return [blockScroll, allowScroll];
};

export default useScrollBlock;

0 comments on commit 82a704b

Please sign in to comment.