diff --git a/packages/web-react/package.json b/packages/web-react/package.json
index 9d2d3ecef4..3386b44d6e 100644
--- a/packages/web-react/package.json
+++ b/packages/web-react/package.json
@@ -58,6 +58,7 @@
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-standard": "5.0.0",
+ "html-react-parser": "^5.0.6",
"jest": "29.7.0",
"jest-cli": "29.7.0",
"jest-environment-jsdom": "29.7.0",
@@ -79,6 +80,7 @@
"peerDependencies": {
"@lmc-eu/spirit-icons": "*",
"@lmc-eu/spirit-web": "*",
+ "html-react-parser": "^5.0.6",
"react": "^17.0.2 || ^18.0.0",
"react-dom": "^17.0.2 || ^18.0.0"
},
diff --git a/packages/web-react/src/components/Icon/Icon.tsx b/packages/web-react/src/components/Icon/Icon.tsx
index bb793da3ae..33e5b440af 100644
--- a/packages/web-react/src/components/Icon/Icon.tsx
+++ b/packages/web-react/src/components/Icon/Icon.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import { useIcon, useStyleProps } from '../../hooks';
import { IconProps } from '../../types';
+import { htmlParser } from '../../utils/htmlParser';
const defaultProps = {
ariaHidden: true,
@@ -16,6 +17,14 @@ export const Icon = (props: IconProps): JSX.Element => {
icon = `
${title}${icon}`;
}
+ // @deprecated Usage of `html-react-parser` will be required in the next major version.
+ if (typeof window === 'undefined' && htmlParser == null) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ 'Icon component is not supported in SSR without use of `html-react-parser`. Please install, missing peer dependency.',
+ );
+ }
+
return (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Incompatible HTMLElement and SVGSVGElement
@@ -24,13 +33,15 @@ export const Icon = (props: IconProps): JSX.Element => {
fill="none"
width={boxSize}
height={boxSize}
- // eslint-disable-next-line react/no-danger
- dangerouslySetInnerHTML={{ __html: icon }}
aria-hidden={ariaHidden}
+ // @deprecated Usage of dangerouslySetInnerHTML is discouraged due to support of SSR and will be removed in the next major version.
+ {...(typeof window !== 'undefined' ? { dangerouslySetInnerHTML: { __html: icon } } : {})}
{...otherProps}
{...styleProps}
className={styleProps.className}
- />
+ >
+ {typeof window === 'undefined' && htmlParser != null ? htmlParser(icon) : null}
+
);
};
diff --git a/packages/web-react/src/components/Icon/README.md b/packages/web-react/src/components/Icon/README.md
index a600443f7d..35f214b028 100644
--- a/packages/web-react/src/components/Icon/README.md
+++ b/packages/web-react/src/components/Icon/README.md
@@ -2,6 +2,30 @@
Icons are graphical metaphors or symbols that can be used to compliment existing experiences.
+## 🚀 Getting started
+
+To use this component in your project you need to run following command using [npm](https://www.npmjs.com/):
+
+```bash
+npm install -S @lcm-eu/spirit-icons html-react-parser
+```
+
+If you prefer [Yarn](https://yarnpkg.com/), use the following command instead:
+
+```bash
+yarn add @lcm-eu/spirit-icons html-react-parser
+```
+
+### 📦 Dependencies
+
+Both packages are required as **peer dependency** to keep package size as low as possible.
+So they will not be automatically installed with `@lmc-eu/spirit-web-react`.
+
+- [`@lmc-eu/spirit-icons`](https://github.com/lmc-eu/spirit-design-system/tree/main/packages/icons) - Spirit Icons package
+- [`html-react-parser`](https://www.npmjs.com/package/html-react-parser) - HTML to React parser (avoid usage of `dangerouslySetInnerHTML` on server side)
+
+## 📝 Usage
+
```jsx
import { Icon, IconsProvider } from '@lmc-eu/spirit-web-react/components';
import icons from '@lmc-eu/spirit-icons/icons';
@@ -14,7 +38,7 @@ import icons from '@lmc-eu/spirit-icons/icons';
```
-## API
+## 🧩 API
| Name | Type | Default | Required | Description |
| ------------------ | --------------- | ------- | -------- | ------------------------- |
diff --git a/packages/web-react/src/utils/htmlParser.ts b/packages/web-react/src/utils/htmlParser.ts
new file mode 100644
index 0000000000..a2400377f1
--- /dev/null
+++ b/packages/web-react/src/utils/htmlParser.ts
@@ -0,0 +1,3 @@
+import parse from 'html-react-parser';
+
+export const htmlParser = typeof window === 'undefined' ? parse : null;
diff --git a/yarn.lock b/yarn.lock
index 52b7e7dad0..36a1963098 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11126,6 +11126,13 @@ domexception@^4.0.0:
dependencies:
webidl-conversions "^7.0.0"
+domhandler@5.0.3, domhandler@^5.0.2, domhandler@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
+ integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+ dependencies:
+ domelementtype "^2.3.0"
+
domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
@@ -11133,13 +11140,6 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"
-domhandler@^5.0.2, domhandler@^5.0.3:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
- integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
- dependencies:
- domelementtype "^2.3.0"
-
domutils@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
@@ -11156,7 +11156,7 @@ domutils@^1.5.1, domutils@^1.7.0:
dom-serializer "0"
domelementtype "1"
-domutils@^3.0.1:
+domutils@^3.0.1, domutils@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
@@ -11400,7 +11400,7 @@ entities@^2.0.0, entities@^2.2.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
-entities@^4.2.0:
+entities@^4.2.0, entities@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
@@ -14355,6 +14355,14 @@ hot-shots@10.0.0:
optionalDependencies:
unix-dgram "2.x"
+html-dom-parser@5.0.4:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-5.0.4.tgz#2941a762317d088e747db31c8cf290987ec30a55"
+ integrity sha512-azy8THLKd4Ar0OVJpEgX+MSjYvKdNDWlGiRBIlovMqEQYMAnLLXBhhiSwjylDD3RDdcCYT8Utg6uoRDeLHUyHg==
+ dependencies:
+ domhandler "5.0.3"
+ htmlparser2 "9.0.0"
+
html-encoding-sniffer@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9"
@@ -14367,6 +14375,16 @@ html-escaper@^2.0.0:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+html-react-parser@^5.0.6:
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-5.0.6.tgz#ee9e8ae404aa38cfbaf3825cb26fabced46024a1"
+ integrity sha512-aPSzFhO2bK/L/mYQbMwFz+1QG8nhxozbwENt/52HTApasrBvDX87MFD5uSQIjq7Io0bnKzH4uh7PM42zZ4ag9A==
+ dependencies:
+ domhandler "5.0.3"
+ html-dom-parser "5.0.4"
+ react-property "2.0.2"
+ style-to-js "1.1.9"
+
html-tags@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
@@ -14377,6 +14395,16 @@ html-tags@^3.3.1:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce"
integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==
+htmlparser2@9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.0.0.tgz#e431142b7eeb1d91672742dea48af8ac7140cddb"
+ integrity sha512-uxbSI98wmFT/G4P2zXx4OVx04qWUmyFPrD2/CNepa2Zo3GPNaCaaxElDgwUrwYWkK1nr9fft0Ya8dws8coDLLQ==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+ domutils "^3.1.0"
+ entities "^4.5.0"
+
htmlparser2@^3.9.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
@@ -14672,6 +14700,11 @@ init-package-json@3.0.2, init-package-json@^3.0.2:
validate-npm-package-license "^3.0.4"
validate-npm-package-name "^4.0.0"
+inline-style-parser@0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.2.tgz#d498b4e6de0373458fc610ff793f6b14ebf45633"
+ integrity sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==
+
inquirer-autocomplete-prompt@^1.0.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.4.0.tgz#e767592f747e3d5bb6336fe71fb4094352e4c317"
@@ -20578,6 +20611,11 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.0.0.tgz#026f6c4a27dbe33bf4a35655b9e1327c4e55e3f5"
integrity sha512-yUcBYdBBbo3QiPsgYDcfQcIkGZHfxOaoE6HLSnr1sPzMhdyxusbfKOSUbSd/ocGi32dxcj366PsTj+5oggeKKw==
+react-property@2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.2.tgz#d5ac9e244cef564880a610bc8d868bd6f60fdda6"
+ integrity sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==
+
react-refresh@^0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
@@ -22599,6 +22637,20 @@ style-search@^0.1.0:
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=
+style-to-js@1.1.9:
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.9.tgz#5bdc23ba7624016094a19d6ea90fa3f98bee34c4"
+ integrity sha512-6bkwhOlPOx+wKiHVlPTHjUqM4zDKv9pyccehB8zetZL0hhQ7MVp7UEWUsohjiMdxwhSsEdjMrEve+8qzUVmY4w==
+ dependencies:
+ style-to-object "1.0.4"
+
+style-to-object@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.4.tgz#496fded508ce520eca13e738e8af33b8b5af98f2"
+ integrity sha512-KyNO6mfijxSnypdvEjeXlhvbGPSh0l1zBJp80n+ncBQvrEbSwBHwZCpo0xz6Q4AKSPfXowWwypCBAUAdfz3rFQ==
+ dependencies:
+ inline-style-parser "0.2.2"
+
stylelint-config-prettier@9.0.5:
version "9.0.5"
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-9.0.5.tgz#9f78bbf31c7307ca2df2dd60f42c7014ee9da56e"