💄(app-desk) handle svg as react component

The svg in nextjs was not handled as a react component, it was
not possible to change dynamically the color of the svg by example.
We add the @svgr/webpack, it will handle the svg as react component.
We keep as well the way next.js handle the svg, so we can use both
ways.
To handle the svg in the next way we need to add the
`?url` at the end of the svg import.
This commit is contained in:
Anthony LC
2024-01-26 13:07:46 +01:00
committed by Anthony LC
parent 32e42e126d
commit ce55721b5d
9 changed files with 1202 additions and 25 deletions

View File

@@ -8,9 +8,23 @@ const createJestConfig = nextJest({
// Add any custom config to be passed to Jest
const config: Config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
testEnvironment: 'jsdom',
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config);
const jestConfig = async () => {
const nextJestConfig = await createJestConfig(config)();
return {
...nextJestConfig,
moduleNameMapper: {
'\\.svg$': '<rootDir>/jest/mocks/svg.js',
'^.+\\.svg\\?url$': `<rootDir>/jest/mocks/fileMock.js`,
...nextJestConfig.moduleNameMapper,
},
};
};
export default jestConfig;

View File

@@ -0,0 +1,16 @@
module.exports = {
src: '/img.jpg',
height: 40,
width: 40,
blurDataURL: 'data:image/png;base64,imagedata',
};
if (
(typeof exports.default === 'function' ||
(typeof exports.default === 'object' && exports.default !== null)) &&
typeof exports.default.__esModule === 'undefined'
) {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}

View File

@@ -0,0 +1,3 @@
const nameMock = 'svg';
export default nameMock;
export const ReactComponent = 'svg';

View File

@@ -1,6 +1,33 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
webpack(config) {
// Grab the existing rule that handles SVG imports
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.('.svg'),
);
config.module.rules.push(
// Reapply the existing rule, but only for svg imports ending in ?url
{
...fileLoaderRule,
test: /\.svg$/i,
resourceQuery: /url/, // *.svg?url
},
// Convert all other *.svg imports to React components
{
test: /\.svg$/i,
issuer: fileLoaderRule.issuer,
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
use: ['@svgr/webpack'],
},
);
// Modify the file loader rule to ignore *.svg, since we have it handled now.
fileLoaderRule.exclude = /\.svg$/i;
return config;
},
};
module.exports = nextConfig;

View File

@@ -26,6 +26,7 @@
"zustand": "4.5.0"
},
"devDependencies": {
"@svgr/webpack": "8.1.0",
"@tanstack/react-query-devtools": "5.18.1",
"@testing-library/jest-dom": "6.4.1",
"@testing-library/react": "14.2.1",

View File

@@ -8,11 +8,11 @@ import { Box, Text } from '@/components/';
import { LanguagePicker } from '../Language/';
import { default as IconCells } from './assets/icon-cells.svg';
import { default as IconDesk } from './assets/icon-desk.svg';
import { default as IconFAQ } from './assets/icon-faq.svg';
import { default as IconGouv } from './assets/icon-gouv.svg';
import { default as IconMarianne } from './assets/icon-marianne.svg';
import { default as IconCells } from './assets/icon-cells.svg?url';
import { default as IconDesk } from './assets/icon-desk.svg?url';
import { default as IconFAQ } from './assets/icon-faq.svg?url';
import { default as IconGouv } from './assets/icon-gouv.svg?url';
import { default as IconMarianne } from './assets/icon-marianne.svg?url';
const RedStripe = styled.div`
position: absolute;

View File

@@ -6,7 +6,7 @@ import styled from 'styled-components';
import { Box, Text } from '@/components/';
import { default as IconLanguage } from './assets/icon-language.svg';
import IconLanguage from './assets/icon-language.svg?url';
const SelectStyled = styled(Select)<{ $isSmall?: boolean }>`
flex-shrink: 0;

View File

@@ -1,5 +1,18 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
declare module '*.svg' {
import * as React from 'react';
const ReactComponent: React.FunctionComponent<
React.SVGProps<SVGSVGElement> & {
title?: string;
}
>;
export default ReactComponent;
}
declare module '*.svg?url' {
const content: string;
export default content;
}

File diff suppressed because it is too large Load Diff