Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codegouvfr/react-dsfr",
"version": "1.21.1",
"version": "1.22.0-rc.1",
"description": "French State Design System React integration library",
"repository": {
"type": "git",
Expand Down
21 changes: 12 additions & 9 deletions src/next-appdir/DsfrHead.tsx → src/next-app-router/DsfrHead.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useMemo } from "react";
import { objectKeys } from "tsafe/objectKeys";
import { getAssetUrl } from "../tools/getAssetUrl";
import AppleTouchIcon from "../dsfr/favicon/apple-touch-icon.png";
import FaviconSvg from "../dsfr/favicon/favicon.svg";
import FaviconIco from "../dsfr/favicon/favicon.ico";
import AppleTouchIcon from "@codegouvfr/react-dsfr/dsfr/favicon/apple-touch-icon.png";
import FaviconSvg from "@codegouvfr/react-dsfr/dsfr/favicon/favicon.svg";
import FaviconIco from "@codegouvfr/react-dsfr/dsfr/favicon/favicon.ico";
import { getScriptToRunAsap } from "../useIsDark/scriptToRunAsap";
import { fontUrlByFileBasename } from "./zz_internal/fontUrlByFileBasename";
import { getDefaultColorSchemeServerSide } from "./zz_internal/defaultColorScheme";
Expand All @@ -12,16 +13,14 @@ import { assert } from "tsafe/assert";
//NOTE: As of now there is no way to enforce ordering in Next Appdir
//See: https://github.com/vercel/next.js/issues/16630
// @import url(...) doesn't work. Using Sass and @use is our last resort.
import "../assets/dsfr_plus_icons.scss";
import "@codegouvfr/react-dsfr/assets/dsfr_plus_icons.scss";
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- used in doc
import type { startReactDsfr } from "./zz_internal/start";

export type DsfrHeadProps = {
/** If not provided no fonts are preloaded.
* Preloading of fonts is only enabled in production.
*/
preloadFonts?: (keyof typeof fontUrlByFileBasename)[];
Link: Function;
/**
* When set, the value will be used as the nonce attribute of subsequent script tags.
*
Expand Down Expand Up @@ -52,7 +51,11 @@ export type DsfrHeadProps = {

const isProduction = process.env.NODE_ENV !== "development";

export function DsfrHead(props: DsfrHeadProps) {
export function DsfrHeadBase(
props: DsfrHeadProps & {
Link: Function;
}
) {
const {
preloadFonts = [],
Link,
Expand All @@ -66,7 +69,7 @@ export function DsfrHead(props: DsfrHeadProps) {
const defaultColorScheme = getDefaultColorSchemeServerSide();

useMemo(() => {
setLink({ "Link": Link as any });
setLink({ Link: Link as any });
}, [Link]);

return (
Expand Down Expand Up @@ -97,7 +100,7 @@ export function DsfrHead(props: DsfrHeadProps) {
suppressHydrationWarning
nonce={nonce}
dangerouslySetInnerHTML={{
"__html": getScriptToRunAsap({
__html: getScriptToRunAsap({
defaultColorScheme,
nonce,
trustedTypesPolicyName
Expand Down
138 changes: 138 additions & 0 deletions src/next-app-router/DsfrProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"use client";
/* eslint-disable @typescript-eslint/no-explicit-any */

import React, { useMemo, useEffect } from "react";
import type { ReactNode } from "react";
import { isBrowser } from "../tools/isBrowser";
import { SsrIsDarkProvider } from "../useIsDark/server";
import type { DefaultColorScheme } from "./zz_internal/defaultColorScheme";
import { setUseLang } from "../i18n";
import { setLink } from "../link";
import { start } from "../start";

export type DsfrProviderProps = {
children: ReactNode;
lang: string | undefined;
/** Default: false */
verbose?: boolean;
/**
* When true, the nonce of the script tag will be checked, fetched from {@link DsfrHead} component and injected in react-dsfr scripts.
*
* @see https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes/nonce
* @default false
*/
doCheckNonce?: boolean;
/**
* Enable Trusted Types with a custom policy name.
*
* Don't forget to also add the policy name in {@link DsfrHead} component.
*
* `<trustedTypesPolicyName>` and `<trustedTypesPolicyName>-asap` should be set in your Content-Security-Policy header.
*
* For example:
* ```txt
* With a policy name of "react-dsfr":
* Content-Security-Policy:
* require-trusted-types-for 'script';
* trusted-types react-dsfr react-dsfr-asap nextjs nextjs#bundler;
* ```
*
* @see https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types
* @see {@link DEFAULT_TRUSTED_TYPES_POLICY_NAME}
* @default "react-dsfr"
*/
trustedTypesPolicyName?: string;
};

export function DsfrProviderBase(
props: DsfrProviderProps & {
Link: Function;
defaultColorScheme: DefaultColorScheme;
}
) {
const {
children,
lang,
Link,
defaultColorScheme,
verbose = false,
doCheckNonce = false,
trustedTypesPolicyName = "react-dsfr"
} = props;

/*
useEffect(() => {
dsfrEffect();
}, []);
*/

useMemo(() => {
if (!isBrowser) {
return;
}

start({
defaultColorScheme,
verbose,
doCheckNonce,
trustedTypesPolicyName,
"nextParams": {
"doPersistDarkModePreferenceWithCookie": false,
"registerEffectAction": action => {
console.log("registerEffectAction", action);

if (isAfterFirstEffect) {
console.log("run now");
action();
} else {
console.log("push");
actions.push(action);
}
}
}
});
}, []);

useMemo(() => {
if (lang === undefined) {
return;
}
setUseLang({ useLang: () => lang });
}, [lang]);

useMemo(() => {
setLink({ Link: Link as any });
}, [Link]);

if (isBrowser) {
return <>{children}</>;
}

const isDark = defaultColorScheme === "dark" ? true : false;

return <SsrIsDarkProvider value={isDark}>{children}</SsrIsDarkProvider>;
}

let isAfterFirstEffect = false;
const actions: (() => void)[] = [];

function dsfrEffect(): void {
if (isAfterFirstEffect) {
return;
}
isAfterFirstEffect = true;
actions.forEach(action => {
console.log("running action", action);
action();
});
}

export function StartDsfrOnHydration() {
useEffect(() => {
console.log("wesh hydratation!");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

io

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@revolunet oula merci pardon pardon!


dsfrEffect();
}, []);

return null;
}
43 changes: 43 additions & 0 deletions src/next-app-router/getHtmlAttributes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { data_fr_scheme, data_fr_theme } from "../useIsDark/constants";
import type { ColorScheme } from "../useIsDark";
import {
type DefaultColorScheme,
setDefaultColorSchemeServerSide
} from "./zz_internal/defaultColorScheme";
import { setUseLang } from "../i18n";

const suppressHydrationWarning = true;

export function createGetHtmlAttributes(params: { defaultColorScheme: DefaultColorScheme }) {
const { defaultColorScheme } = params;

function getHtmlAttributes(params: {
lang: string | undefined;
}): { suppressHydrationWarning: true; lang?: string } & (
| Record<typeof data_fr_scheme | typeof data_fr_theme, ColorScheme>
| {}
) {
const { lang } = params;

setDefaultColorSchemeServerSide({ defaultColorScheme });

if (lang !== undefined) {
setUseLang({ useLang: () => lang });
}

if (defaultColorScheme === "system") {
return {
lang,
suppressHydrationWarning
};
}

return {
lang,
suppressHydrationWarning,
[data_fr_scheme]: defaultColorScheme,
[data_fr_theme]: defaultColorScheme
};
}
return { getHtmlAttributes };
}
2 changes: 1 addition & 1 deletion src/next-appdir/index.ts → src/next-app-router/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export type { RegisterLink } from "../link";
export type { DefaultColorScheme } from "./zz_internal/defaultColorScheme";
export { startReactDsfr } from "./zz_internal/start";
export { DsfrProviderBase, type DsfrProviderProps, StartDsfrOnHydration } from "./DsfrProvider";
2 changes: 2 additions & 0 deletions src/next-app-router/server-only-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { createGetHtmlAttributes } from "./getHtmlAttributes";
export { DsfrHeadBase, type DsfrHeadProps } from "./DsfrHead";
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { assert } from "tsafe/assert";

import type { ColorScheme } from "../../useIsDark";

export type DefaultColorScheme = ColorScheme | "system";
Expand Down
23 changes: 23 additions & 0 deletions src/next-app-router/zz_internal/fontUrlByFileBasename.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import marianneLightWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Light.woff2";
import marianneItalicWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Light_Italic.woff2";
import marianneRegularWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Regular.woff2";
import marianneRegularItalicWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Regular_Italic.woff2";
import marianneMediumWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Medium.woff2";
import marianneMediumItalicWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Medium_Italic.woff2";
import marianneBoldWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Bold.woff2";
import marianneBoldItalicWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Bold_Italic.woff2";
import spectralRegularWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Spectral-Regular.woff2";
import spectralExtraBoldWoff2Url from "@codegouvfr/react-dsfr/dsfr/fonts/Spectral-ExtraBold.woff2";

export const fontUrlByFileBasename = {
"Marianne-Light": marianneLightWoff2Url,
"Marianne-Light_Italic": marianneItalicWoff2Url,
"Marianne-Regular": marianneRegularWoff2Url,
"Marianne-Regular_Italic": marianneRegularItalicWoff2Url,
"Marianne-Medium": marianneMediumWoff2Url,
"Marianne-Medium_Italic": marianneMediumItalicWoff2Url,
"Marianne-Bold": marianneBoldWoff2Url,
"Marianne-Bold_Italic": marianneBoldItalicWoff2Url,
"Spectral-Regular": spectralRegularWoff2Url,
"Spectral-ExtraBold": spectralExtraBoldWoff2Url
} as const;
45 changes: 0 additions & 45 deletions src/next-appdir/DsfrProvider.tsx

This file was deleted.

39 changes: 0 additions & 39 deletions src/next-appdir/getHtmlAttributes.tsx

This file was deleted.

Loading