use-dark-mode-v2 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018-present Donavon West
4
+ Copyright (c) 2026-present Anis Tigrini
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,122 @@
1
- # Temporary Holding Version
1
+ # use-dark-mode-v2
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A custom [React Hook](https://react.dev/reference/react/hooks) to help you implement a "dark mode" component for your application.
4
+ The user setting persists to `localStorage`.
5
+
6
+ [![npm version](https://badge.fury.io/js/use-dark-mode-v2.svg)](https://www.npmjs.com/package/use-dark-mode-v2)
7
+
8
+ > **This is a maintained fork of [`use-dark-mode`](https://github.com/donavon/use-dark-mode)** by [Donavon West](https://github.com/donavon).
9
+ > The original package still gets thousands of downloads a week, but it hasn't been released since 2019,
10
+ > can't be installed on React 17+ without `--legacy-peer-deps`, and breaks with server rendering in Next.js.
11
+ > This fork fixes those problems and simplifies the API. All credit for the original design goes to Donavon and its [contributors](#contributors).
12
+
13
+ **📖 Documentation and live demo: https://anistigrini.github.io/use-dark-mode/**
14
+
15
+ ## Installation
16
+
17
+ ```sh
18
+ npm i use-dark-mode-v2
19
+ ```
20
+
21
+ Works with React 16.8 through 19.
22
+
23
+ ## Usage
24
+
25
+ ```jsx
26
+ import useDarkMode from 'use-dark-mode-v2';
27
+
28
+ function ThemeToggle() {
29
+ const darkMode = useDarkMode();
30
+
31
+ return (
32
+ <button onClick={darkMode.toggle}>
33
+ {darkMode.isDarkModeEnabled ? '☀ Light' : '☾ Dark'}
34
+ </button>
35
+ );
36
+ }
37
+ ```
38
+
39
+ The hook adds a `dark-mode` or `light-mode` class to `<body>`, saves the user's choice in `localStorage`,
40
+ follows the OS theme until the user picks one, and keeps every component and tab in sync.
41
+
42
+ `useDarkMode` returns:
43
+
44
+ | Property | Description |
45
+ |---|---|
46
+ | `isDarkModeEnabled` | `true` when dark mode is on. |
47
+ | `toggle()` | Flip the current mode and save it as the user's choice. |
48
+ | `set(isDarkModeEnabled)` | Turn dark mode on (`true`) or off (`false`) and save it as the user's choice. |
49
+ | `reset()` | Forget the user's choice and go back to the default mode. |
50
+
51
+ By default the hook follows the OS theme until the user picks a mode. For a site designed dark-first (or light-first),
52
+ pass `useDarkMode({ defaultMode: 'dark' })`: it then starts dark whatever the OS says.
53
+
54
+ For the full API, the Next.js setup and how to prevent the flash on page load,
55
+ see the [documentation](https://anistigrini.github.io/use-dark-mode/).
56
+
57
+ ## What this fork fixes
58
+
59
+ - React 17, 18 and 19 support ([#68](https://github.com/donavon/use-dark-mode/pull/68), [#70](https://github.com/donavon/use-dark-mode/issues/70), [#96](https://github.com/donavon/use-dark-mode/issues/96))
60
+ - No hydration errors, flash or double-click toggle in Next.js ([#83](https://github.com/donavon/use-dark-mode/issues/83), [#55](https://github.com/donavon/use-dark-mode/issues/55), [#66](https://github.com/donavon/use-dark-mode/issues/66), [#80](https://github.com/donavon/use-dark-mode/issues/80))
61
+ - Works with Vite and other modern bundlers ([#91](https://github.com/donavon/use-dark-mode/issues/91))
62
+ - Respects the user's choice, and follows the OS theme until they make one ([#52](https://github.com/donavon/use-dark-mode/issues/52))
63
+ - No abandoned dependencies, and no crash when storage is unavailable
64
+
65
+ ## Migrating from `use-dark-mode`
66
+
67
+ ```sh
68
+ npm uninstall use-dark-mode && npm i use-dark-mode-v2
69
+ ```
70
+
71
+ Change your imports to `use-dark-mode-v2`, then update the call and what it returns:
72
+
73
+ | `use-dark-mode` | `use-dark-mode-v2` |
74
+ |---|---|
75
+ | `useDarkMode(initialState, config)` | `useDarkMode(config)` |
76
+ | `darkMode.value` | `darkMode.isDarkModeEnabled` |
77
+ | `darkMode.enable()` | `darkMode.set(true)` |
78
+ | `darkMode.disable()` | `darkMode.set(false)` |
79
+ | `darkMode.toggle()` | `darkMode.toggle()` (unchanged) |
80
+
81
+ The other options and the default `storageKey` are unchanged, so your users keep their saved preference.
82
+ `initialState` was only used in browsers without an OS theme setting, so dropping it changes nothing for most apps.
83
+ If you meant it as "start dark", pass `{ defaultMode: 'dark' }`.
84
+ Two behaviours changed on purpose: nothing is saved until the user picks a mode, and once they have, OS theme changes no longer override it (use `reset()` to follow the OS again).
85
+
86
+ ## Sample Apps
87
+
88
+ If you have an app built with `use-dark-mode-v2` you would like to include on this list, open a PR.
89
+
90
+ * [Original demo app on CodeSandbox](https://codesandbox.io/s/mzj64x80ny) (uses the original `use-dark-mode`) - by [@donavon](https://twitter.com/donavon)
91
+
92
+ ## License
93
+
94
+ **[MIT](LICENSE)** Licensed. Original work © Donavon West.
95
+
96
+ ## Contributors
97
+
98
+ These are the contributors to the original `use-dark-mode`. Thanks goes to these wonderful people ([emoji key](https://github.com/all-contributors/all-contributors#emoji-key)):
99
+
100
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
101
+ <!-- prettier-ignore-start -->
102
+ <!-- markdownlint-disable -->
103
+ <table>
104
+ <tr>
105
+ <td align="center"><a href="http://donavon.com"><img src="https://avatars3.githubusercontent.com/u/887639?v=4" width="100px;" alt=""/><br /><sub><b>Donavon West</b></sub></a><br /><a href="#infra-donavon" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/donavon/use-dark-mode/commits?author=donavon" title="Tests">⚠️</a> <a href="#example-donavon" title="Examples">💡</a> <a href="#ideas-donavon" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-donavon" title="Maintenance">🚧</a> <a href="https://github.com/donavon/use-dark-mode/pulls?q=is%3Apr+reviewed-by%3Adonavon" title="Reviewed Pull Requests">👀</a> <a href="#tool-donavon" title="Tools">🔧</a> <a href="https://github.com/donavon/use-dark-mode/commits?author=donavon" title="Code">💻</a></td>
106
+ <td align="center"><a href="https://github.com/revelcw"><img src="https://avatars2.githubusercontent.com/u/29359616?v=4" width="100px;" alt=""/><br /><sub><b>Revel Carlberg West</b></sub></a><br /><a href="#ideas-revelcw" title="Ideas, Planning, & Feedback">🤔</a></td>
107
+ <td align="center"><a href="https://github.com/Andarist"><img src="https://avatars2.githubusercontent.com/u/9800850?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Burzyński</b></sub></a><br /><a href="https://github.com/donavon/use-dark-mode/commits?author=Andarist" title="Code">💻</a></td>
108
+ <td align="center"><a href="https://github.com/wKovacs64"><img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;" alt=""/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="https://github.com/donavon/use-dark-mode/commits?author=wKovacs64" title="Code">💻</a></td>
109
+ <td align="center"><a href="https://github.com/fxbabys"><img src="https://avatars1.githubusercontent.com/u/24556921?v=4" width="100px;" alt=""/><br /><sub><b>Jeremy</b></sub></a><br /><a href="#userTesting-fxbabys" title="User Testing">📓</a> <a href="https://github.com/donavon/use-dark-mode/issues?q=author%3Afxbabys" title="Bug reports">🐛</a></td>
110
+ <td align="center"><a href="http://janosh.io"><img src="https://avatars0.githubusercontent.com/u/30958850?v=4" width="100px;" alt=""/><br /><sub><b>Janosh Riebesell</b></sub></a><br /><a href="https://github.com/donavon/use-dark-mode/commits?author=janosh" title="Documentation">📖</a></td>
111
+ <td align="center"><a href="http://hipstersmoothie.com"><img src="https://avatars3.githubusercontent.com/u/1192452?v=4" width="100px;" alt=""/><br /><sub><b>Andrew Lisowski</b></sub></a><br /><a href="https://github.com/donavon/use-dark-mode/commits?author=hipstersmoothie" title="Documentation">📖</a></td>
112
+ </tr>
113
+ <tr>
114
+ <td align="center"><a href="https://jorgegonzalez.io"><img src="https://avatars2.githubusercontent.com/u/12901172?v=4" width="100px;" alt=""/><br /><sub><b>Jorge Gonzalez</b></sub></a><br /><a href="https://github.com/donavon/use-dark-mode/commits?author=jorgegonzalez" title="Code">💻</a></td>
115
+ </tr>
116
+ </table>
117
+
118
+ <!-- markdownlint-enable -->
119
+ <!-- prettier-ignore-end -->
120
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
121
+
122
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
@@ -0,0 +1 @@
1
+ var e=require("react"),t=require("use-sync-external-store/shim"),n=new Map,r=new Map,o=function(e){(n.get(e)||[]).forEach(function(e){return e()})},a=function(){},u=function(u,i,s){void 0===s&&(s=globalThis);var c,d,l=function(){try{return i||s.localStorage||null}catch(e){return null}},f=function(){var e=function(){if(r.has(u))return r.get(u);try{var e=l();return e?e.getItem(u):null}catch(e){return null}}();if(e!==c){c=e;try{d=null===e?void 0:JSON.parse(e)}catch(e){d=void 0}}return d},v=function(){try{l().removeItem(u),r.delete(u)}catch(e){r.set(u,null)}o(u)},m=function(e){n.has(u)||n.set(u,new Set);var t=n.get(u);t.add(e);var r=function(t){t.key!==u&&null!==t.key||e()};return s.addEventListener&&s.addEventListener("storage",r),function(){t.delete(e),0===t.size&&n.delete(u),s.removeEventListener&&s.removeEventListener("storage",r)}};return function(n){var i=t.useSyncExternalStore(m,f,a);return[void 0===i?n:i,e.useCallback(function(e){var t=f();!function(e){var t=JSON.stringify(e);try{l().setItem(u,t),r.delete(u)}catch(e){r.set(u,t)}o(u)}("function"==typeof e?e(void 0===t?n:t):e)},[n]),v]}},i=function(){},s={classList:{add:i,remove:i}},c=function(t){var n=e.useState(void 0),r=n[0],o=n[1];return[void 0===r?t:r,e.useCallback(function(e){o(function(n){return"function"==typeof e?e(void 0===n?t:n):e})},[t]),e.useCallback(function(){return o(void 0)},[])]};module.exports=function(n){void 0===n&&(n={});var r=n.defaultMode;void 0===r&&(r="system");var o=n.element,d=n.classNameDark,l=n.classNameLight,f=n.onChange,v=n.storageKey;void 0===v&&(v="darkMode");var m=n.storageProvider,g=n.global,h=e.useMemo(function(){return function(e,t,n){void 0===n&&(n=globalThis);var r=e?u(e,t,n):c,o=n.matchMedia?n.matchMedia("(prefers-color-scheme: dark)"):null,a=!!o&&"(prefers-color-scheme: dark)"===o.media,d=n.document&&n.document.body||s;return{usePersistedDarkModeState:r,getDefaultOnChange:function(e,t,n){return void 0===e&&(e=d),void 0===t&&(t="dark-mode"),void 0===n&&(n="light-mode"),function(r){e.classList.add(r?t:n),e.classList.remove(r?n:t)}},getSystemSnapshot:function(){return a?o.matches:void 0},subscribeToSystem:function(e){return a?o.addEventListener?(o.addEventListener("change",e),function(){return o.removeEventListener("change",e)}):(o.addListener(e),function(){return o.removeListener(e)}):i}}}(v,m,g)},[v,m,g]),y=h.usePersistedDarkModeState,S=h.getDefaultOnChange,k=t.useSyncExternalStore(h.subscribeToSystem,h.getSystemSnapshot,a),b=y("system"===r?!0===k:"dark"===r),L=b[0],E=b[1],M=b[2],p=e.useMemo(function(){return f||S(o,d,l)},[f,o,d,l,S]);return e.useEffect(function(){p(L)},[p,L]),{isDarkModeEnabled:L,set:e.useCallback(function(e){return E(e)},[E]),toggle:e.useCallback(function(){return E(function(e){return!e})},[E]),reset:M}};
@@ -0,0 +1 @@
1
+ import{useCallback as e,useState as t,useEffect as n,useMemo as r}from"react";import{useSyncExternalStore as o}from"use-sync-external-store/shim";var i=new Map,a=new Map,u=function(e){(i.get(e)||[]).forEach(function(e){return e()})},s=function(){},c=function(t,n,r){void 0===r&&(r=globalThis);var c,d,f=function(){try{return n||r.localStorage||null}catch(e){return null}},v=function(){var e=function(){if(a.has(t))return a.get(t);try{var e=f();return e?e.getItem(t):null}catch(e){return null}}();if(e!==c){c=e;try{d=null===e?void 0:JSON.parse(e)}catch(e){d=void 0}}return d},l=function(){try{f().removeItem(t),a.delete(t)}catch(e){a.set(t,null)}u(t)},m=function(e){i.has(t)||i.set(t,new Set);var n=i.get(t);n.add(e);var o=function(n){n.key!==t&&null!==n.key||e()};return r.addEventListener&&r.addEventListener("storage",o),function(){n.delete(e),0===n.size&&i.delete(t),r.removeEventListener&&r.removeEventListener("storage",o)}};return function(n){var r=o(m,v,s);return[void 0===r?n:r,e(function(e){var r=v();!function(e){var n=JSON.stringify(e);try{f().setItem(t,n),a.delete(t)}catch(e){a.set(t,n)}u(t)}("function"==typeof e?e(void 0===r?n:r):e)},[n]),l]}},d=function(){},f={classList:{add:d,remove:d}},v=function(n){var r=t(void 0),o=r[0],i=r[1];return[void 0===o?n:o,e(function(e){i(function(t){return"function"==typeof e?e(void 0===t?n:t):e})},[n]),e(function(){return i(void 0)},[])]};export default function(t){void 0===t&&(t={});var i=t.defaultMode;void 0===i&&(i="system");var a=t.element,u=t.classNameDark,l=t.classNameLight,m=t.onChange,g=t.storageKey;void 0===g&&(g="darkMode");var h=t.storageProvider,y=t.global,L=r(function(){return function(e,t,n){void 0===n&&(n=globalThis);var r=e?c(e,t,n):v,o=n.matchMedia?n.matchMedia("(prefers-color-scheme: dark)"):null,i=!!o&&"(prefers-color-scheme: dark)"===o.media,a=n.document&&n.document.body||f;return{usePersistedDarkModeState:r,getDefaultOnChange:function(e,t,n){return void 0===e&&(e=a),void 0===t&&(t="dark-mode"),void 0===n&&(n="light-mode"),function(r){e.classList.add(r?t:n),e.classList.remove(r?n:t)}},getSystemSnapshot:function(){return i?o.matches:void 0},subscribeToSystem:function(e){return i?o.addEventListener?(o.addEventListener("change",e),function(){return o.removeEventListener("change",e)}):(o.addListener(e),function(){return o.removeListener(e)}):d}}}(g,h,y)},[g,h,y]),p=L.usePersistedDarkModeState,S=L.getDefaultOnChange,k=o(L.subscribeToSystem,L.getSystemSnapshot,s),b=p("system"===i?!0===k:"dark"===i),E=b[0],M=b[1],D=b[2],N=r(function(){return m||S(a,u,l)},[m,a,u,l,S]);return n(function(){N(E)},[N,E]),{isDarkModeEnabled:E,set:e(function(e){return M(e)},[M]),toggle:e(function(){return M(function(e){return!e})},[M]),reset:D}}
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react"),require("use-sync-external-store/shim")):"function"==typeof define&&define.amd?define(["react","use-sync-external-store/shim"],t):e.useDarkModeV2=t(e.react,e.shim)}(this,function(e,t){var n=new Map,r=new Map,o=function(e){(n.get(e)||[]).forEach(function(e){return e()})},u=function(){},a=function(a,i,s){void 0===s&&(s=globalThis);var c,d,f=function(){try{return i||s.localStorage||null}catch(e){return null}},l=function(){var e=function(){if(r.has(a))return r.get(a);try{var e=f();return e?e.getItem(a):null}catch(e){return null}}();if(e!==c){c=e;try{d=null===e?void 0:JSON.parse(e)}catch(e){d=void 0}}return d},v=function(){try{f().removeItem(a),r.delete(a)}catch(e){r.set(a,null)}o(a)},m=function(e){n.has(a)||n.set(a,new Set);var t=n.get(a);t.add(e);var r=function(t){t.key!==a&&null!==t.key||e()};return s.addEventListener&&s.addEventListener("storage",r),function(){t.delete(e),0===t.size&&n.delete(a),s.removeEventListener&&s.removeEventListener("storage",r)}};return function(n){var i=t.useSyncExternalStore(m,l,u);return[void 0===i?n:i,e.useCallback(function(e){var t=l();!function(e){var t=JSON.stringify(e);try{f().setItem(a,t),r.delete(a)}catch(e){r.set(a,t)}o(a)}("function"==typeof e?e(void 0===t?n:t):e)},[n]),v]}},i=function(){},s={classList:{add:i,remove:i}},c=function(t){var n=e.useState(void 0),r=n[0],o=n[1];return[void 0===r?t:r,e.useCallback(function(e){o(function(n){return"function"==typeof e?e(void 0===n?t:n):e})},[t]),e.useCallback(function(){return o(void 0)},[])]};return function(n){void 0===n&&(n={});var r=n.defaultMode;void 0===r&&(r="system");var o=n.element,d=n.classNameDark,f=n.classNameLight,l=n.onChange,v=n.storageKey;void 0===v&&(v="darkMode");var m=n.storageProvider,h=n.global,g=e.useMemo(function(){return function(e,t,n){void 0===n&&(n=globalThis);var r=e?a(e,t,n):c,o=n.matchMedia?n.matchMedia("(prefers-color-scheme: dark)"):null,u=!!o&&"(prefers-color-scheme: dark)"===o.media,d=n.document&&n.document.body||s;return{usePersistedDarkModeState:r,getDefaultOnChange:function(e,t,n){return void 0===e&&(e=d),void 0===t&&(t="dark-mode"),void 0===n&&(n="light-mode"),function(r){e.classList.add(r?t:n),e.classList.remove(r?n:t)}},getSystemSnapshot:function(){return u?o.matches:void 0},subscribeToSystem:function(e){return u?o.addEventListener?(o.addEventListener("change",e),function(){return o.removeEventListener("change",e)}):(o.addListener(e),function(){return o.removeListener(e)}):i}}}(v,m,h)},[v,m,h]),y=g.usePersistedDarkModeState,k=g.getDefaultOnChange,S=t.useSyncExternalStore(g.subscribeToSystem,g.getSystemSnapshot,u),b=y("system"===r?!0===S:"dark"===r),p=b[0],L=b[1],E=b[2],M=e.useMemo(function(){return l||k(o,d,f)},[l,o,d,f,k]);return e.useEffect(function(){M(p)},[M,p]),{isDarkModeEnabled:p,set:e.useCallback(function(e){return L(e)},[L]),toggle:e.useCallback(function(){return L(function(e){return!e})},[L]),reset:E}}});
package/package.json CHANGED
@@ -1,6 +1,76 @@
1
1
  {
2
2
  "name": "use-dark-mode-v2",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "publishConfig": {
4
+ "tag": "latest"
5
+ },
6
+ "version": "1.0.0",
7
+ "description": "A custom React Hook to help you implement a \"dark mode\" component.",
8
+ "main": "dist/use-dark-mode-v2.js",
9
+ "umd:main": "dist/use-dark-mode-v2.umd.js",
10
+ "module": "dist/use-dark-mode-v2.m.js",
11
+ "source": "src/index.js",
12
+ "types": "types/index.d.ts",
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/AnisTigrini/use-dark-mode.git"
17
+ },
18
+ "homepage": "https://anistigrini.github.io/use-dark-mode/",
19
+ "bugs": {
20
+ "url": "https://github.com/AnisTigrini/use-dark-mode/issues"
21
+ },
22
+ "scripts": {
23
+ "prepublishOnly": "npm run build",
24
+ "lint": "eslint src",
25
+ "test": "jest --verbose --coverage --silent",
26
+ "test:watch": "jest --watch --runInBand --silent",
27
+ "prebuild": "npm run lint && npm t && rimraf dist",
28
+ "build": "microbundle -o dist/ --sourcemap false --target web",
29
+ "dev": "microbundle watch -o dist/ --sourcemap false --compress false"
30
+ },
31
+ "keywords": [
32
+ "react-hooks",
33
+ "hooks",
34
+ "react",
35
+ "utils",
36
+ "lib",
37
+ "dark-mode"
38
+ ],
39
+ "author": "Anis Tigrini",
40
+ "contributors": [
41
+ "Donavon West (https://github.com/donavon) - original author"
42
+ ],
43
+ "devDependencies": {
44
+ "@babel/core": "^7.2.2",
45
+ "@babel/preset-env": "^7.2.3",
46
+ "@babel/preset-react": "^7.0.0",
47
+ "babel-core": "^7.0.0-bridge.0",
48
+ "babel-jest": "^23.6.0",
49
+ "eslint": "^5.10.0",
50
+ "eslint-config-amex": "^9.0.0",
51
+ "eslint-plugin-react-hooks": "^1.2.0",
52
+ "jest": "^23.6.0",
53
+ "jest-dom": "^3.0.0",
54
+ "microbundle": "^0.9.0",
55
+ "react": "^16.8.0",
56
+ "react-dom": "^16.8.0",
57
+ "react-testing-library": "^5.5.0",
58
+ "rimraf": "^2.6.2"
59
+ },
60
+ "peerDependencies": {
61
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
62
+ },
63
+ "jest": {
64
+ "coverageThreshold": {
65
+ "global": {
66
+ "branches": 100,
67
+ "functions": 100,
68
+ "lines": 100,
69
+ "statements": 100
70
+ }
71
+ }
72
+ },
73
+ "dependencies": {
74
+ "use-sync-external-store": "^1.7.0"
75
+ }
76
+ }
@@ -0,0 +1,30 @@
1
+ declare module 'use-dark-mode-v2' {
2
+ /**
3
+ * A config object allowing you to specify certain aspects of `useDarkMode`
4
+ */
5
+ export interface DarkModeConfig {
6
+ defaultMode?: 'system' | 'dark' | 'light'; // The mode before the user picks one (and after `reset`). Default = "system" (follow the OS).
7
+ classNameDark?: string; // A className to set "dark mode". Default = "dark-mode".
8
+ classNameLight?: string; // A className to set "light mode". Default = "light-mode".
9
+ element?: HTMLElement; // The element to apply the className. Default = `document.body`
10
+ onChange?: (val?: boolean) => void; // Overide the default className handler with a custom callback.
11
+ storageKey?: string | null; // Specify the `localStorage` key. Default = "darkMode". Set to `null` to disable persistent storage.
12
+ storageProvider?: Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>; // A storage provider, e.g. `sessionStorage`. Default = `localStorage`.
13
+ global?: Window; // The global object. Default = `globalThis`.
14
+ }
15
+
16
+ /**
17
+ * An object returned from a call to `useDarkMode`.
18
+ */
19
+ export interface DarkMode {
20
+ readonly isDarkModeEnabled: boolean;
21
+ set: (isDarkModeEnabled: boolean) => void;
22
+ toggle: () => void;
23
+ reset: () => void;
24
+ }
25
+
26
+ /**
27
+ * A custom React Hook to help you implement a "dark mode" component for your application.
28
+ */
29
+ export default function useDarkMode(config?: DarkModeConfig): DarkMode;
30
+ }