diff --git a/README.md b/README.md
index 21b8a6d9..d5506dfb 100644
--- a/README.md
+++ b/README.md
@@ -11,18 +11,33 @@ The `nextjs-themes` library was initially created to achieve a similar functiona
## Features
- ✅ Simple API to toggle between dark and light modes
+
- ✅ Perfect dark mode with just 2 lines of code
-- ✅ Compatible with Tailwind CSS
+
+- ✅ Compatible with Tailwind CSS, StyledComponents, emotion, Material UI, ...
+
+- ✅ Secure by design - we support `nonce` when you want to apply Content Security Policy
+
- ✅ Fully treeshakable (e.g., `import from nextjs-darkmode/hooks`)
+
- ✅ Full TypeScript support
+
- ✅ Utilizes React 18 Server components
+
- ✅ Compatible with all React 18 build systems/tools/frameworks
+
- ✅ System setting with `prefers-color-scheme`
+
- ✅ Supports Next.js 13 & 14 `appDir`
+
- ✅ No flash on load (supports SSG, SSR, ISG, and Server Components)
+
- ✅ Sync theme across tabs and windows
+
- ✅ Apply custom transitions when changing themes
+
- ✅ Manipulate theme via the `useMode` hook
+
- ✅ No cookies when not using the corresponding `ServerTarget`
- ✅ Comprehensive documentation with [Typedoc](https://react18-tools.github.io/nextjs-darkmode)
@@ -190,6 +205,14 @@ When using `ServerTarget`, use the CSS general sibling combinator (~):
`data-sm` -> System preference
+#### Content Security Policy
+
+If you are using CSP rules for CSS files, you can pass `nonce` argument to the `Core` component. If `nonce` is not supplied transition styles will not be applied. This may allow patched transitions throught the page in some cases.
+
+```tsx
+
+```
+
### Images
Show different images based on the current theme:
diff --git a/lib/CHANGELOG.md b/lib/CHANGELOG.md
index ba81540f..32ada8bc 100644
--- a/lib/CHANGELOG.md
+++ b/lib/CHANGELOG.md
@@ -1,5 +1,11 @@
# nextjs-darkmode
+## 0.1.0
+
+### Minor Changes
+
+- Add nonce to support Content Security Policy
+
## 0.0.3
### Patch Changes
diff --git a/lib/package.json b/lib/package.json
index 2392b552..9e17a3eb 100644
--- a/lib/package.json
+++ b/lib/package.json
@@ -2,7 +2,7 @@
"name": "nextjs-darkmode",
"author": "Mayank Kumar Chaudhari ",
"private": false,
- "version": "0.0.3",
+ "version": "0.1.0",
"description": "Unleash the Power of React Server Components! Use dark/light mode on your site with confidence, without losing any advantages of React Server Components",
"license": "MPL-2.0",
"main": "./dist/index.js",
@@ -97,6 +97,10 @@
"Server Components",
"Dark Mode",
"React18 Tools",
+ "Content Security Policy",
+ "Security",
+ "CSP",
+ "nonce",
"Themes",
"Customizable",
"UI Components",
diff --git a/lib/src/client/core/core.tsx b/lib/src/client/core/core.tsx
index ad80724d..e5320b40 100644
--- a/lib/src/client/core/core.tsx
+++ b/lib/src/client/core/core.tsx
@@ -5,13 +5,16 @@ import { useEffect } from "react";
export interface CoreProps {
/** force apply CSS transition property to all the elements during theme switching. E.g., `all .3s` */
t?: string;
+ /** The nonce value for your Content Security Policy. */
+ nonce?: string;
}
/** Modify transition globally to avoid patched transitions */
-const modifyTransition = (themeTransition = "none") => {
+const modifyTransition = (themeTransition = "none", nonce = "") => {
const css = document.createElement("style");
/** split by ';' to prevent CSS injection */
css.textContent = `*{transition:${themeTransition.split(";")[0]} !important;}`;
+ nonce && css.setAttribute("nonce", nonce);
document.head.appendChild(css);
return () => {
@@ -33,7 +36,7 @@ const modifyTransition = (themeTransition = "none") => {
*
* @source - Source code
*/
-export const Core = ({ t }: CoreProps) => {
+export const Core = ({ t, nonce }: CoreProps) => {
const [{ m: mode, s: systemMode }, setThemeState] = useStore();
const resolvedMode = mode === SYSTEM ? systemMode : mode; // resolvedMode is the actual mode that will be used
@@ -58,7 +61,7 @@ export const Core = ({ t }: CoreProps) => {
}, []);
useEffect(() => {
- const restoreTransitions = modifyTransition(t);
+ const restoreTransitions = modifyTransition(t, nonce);
const serverTargetEl = document.querySelector("[data-ndm]");
// We need to always update documentElement to support Tailwind configuration
// skipcq: JS-D008, JS-0042 -> map keyword is shorter
@@ -79,7 +82,7 @@ export const Core = ({ t }: CoreProps) => {
localStorage.setItem(COOKIE_KEY, mode);
if (serverTargetEl)
document.cookie = `${COOKIE_KEY}=${resolvedMode};max-age=31536000;SameSite=Strict;`;
- }, [resolvedMode, systemMode, mode, t]);
+ }, [resolvedMode, systemMode, mode, t, nonce]);
return null;
};
diff --git a/packages/shared/CHANGELOG.md b/packages/shared/CHANGELOG.md
index b32eac07..2c917232 100644
--- a/packages/shared/CHANGELOG.md
+++ b/packages/shared/CHANGELOG.md
@@ -1,5 +1,12 @@
# @repo/shared
+## 0.0.4
+
+### Patch Changes
+
+- Updated dependencies
+ - nextjs-darkmode@0.1.0
+
## 0.0.3
### Patch Changes
diff --git a/packages/shared/package.json b/packages/shared/package.json
index d75bbfb3..93e347bb 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@repo/shared",
- "version": "0.0.3",
+ "version": "0.0.4",
"private": true,
"sideEffects": false,
"main": "./dist/index.js",