@vueless/storybook-dark-mode 9.0.10 → 10.0.1-beta.1
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/README.md +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +86 -0
- package/dist/manager.js +199 -0
- package/dist/preset.js +8 -0
- package/package.json +69 -45
- package/preset.js +1 -7
- package/src/Tool.tsx +45 -46
- package/src/constants.ts +2 -2
- package/src/index.tsx +8 -5
- package/src/preset/manager.tsx +10 -11
- package/src/preset.ts +5 -0
- package/dist/cjs/Tool.js +0 -251
- package/dist/cjs/constants.js +0 -8
- package/dist/cjs/index.js +0 -48
- package/dist/cjs/preset/manager.js +0 -34
- package/dist/esm/Tool.js +0 -242
- package/dist/esm/constants.js +0 -2
- package/dist/esm/index.js +0 -30
- package/dist/esm/preset/manager.js +0 -31
- package/dist/ts/Tool.d.ts +0 -35
- package/dist/ts/constants.d.ts +0 -2
- package/dist/ts/index.d.ts +0 -5
- package/dist/ts/preset/manager.d.ts +0 -1
package/src/Tool.tsx
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { global } from
|
|
3
|
-
import { themes, ThemeVars } from
|
|
4
|
-
import { IconButton } from
|
|
5
|
-
import { MoonIcon, SunIcon } from
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from 'storybook/internal/core-events';
|
|
11
|
-
import { API, useParameter } from 'storybook/manager-api';
|
|
12
|
-
import equal from 'fast-deep-equal';
|
|
13
|
-
import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from './constants';
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { global } from "@storybook/global";
|
|
3
|
+
import { themes, ThemeVars } from "storybook/theming";
|
|
4
|
+
import { IconButton } from "storybook/internal/components";
|
|
5
|
+
import { MoonIcon, SunIcon } from "@storybook/icons";
|
|
6
|
+
import { STORY_CHANGED, SET_STORIES, DOCS_RENDERED } from "storybook/internal/core-events";
|
|
7
|
+
import { API, useParameter } from "storybook/manager-api";
|
|
8
|
+
import equal from "fast-deep-equal";
|
|
9
|
+
import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from "./constants";
|
|
14
10
|
|
|
15
11
|
const { document, window } = global as { document: Document; window: Window };
|
|
16
|
-
|
|
17
|
-
type Mode =
|
|
12
|
+
|
|
13
|
+
type Mode = "light" | "dark";
|
|
18
14
|
|
|
19
15
|
interface DarkModeStore {
|
|
20
16
|
/** The class target in the preview iframe */
|
|
@@ -35,15 +31,16 @@ interface DarkModeStore {
|
|
|
35
31
|
userHasExplicitlySetTheTheme: boolean;
|
|
36
32
|
}
|
|
37
33
|
|
|
38
|
-
const STORAGE_KEY =
|
|
39
|
-
|
|
34
|
+
const STORAGE_KEY = "sb-addon-themes-3";
|
|
35
|
+
|
|
36
|
+
export const prefersDark = window.matchMedia?.("(prefers-color-scheme: dark)");
|
|
40
37
|
|
|
41
|
-
const defaultParams: Required<Omit<DarkModeStore,
|
|
42
|
-
classTarget:
|
|
38
|
+
const defaultParams: Required<Omit<DarkModeStore, "current">> = {
|
|
39
|
+
classTarget: "body",
|
|
43
40
|
dark: themes.dark,
|
|
44
|
-
darkClass: [
|
|
41
|
+
darkClass: ["dark"],
|
|
45
42
|
light: themes.light,
|
|
46
|
-
lightClass: [
|
|
43
|
+
lightClass: ["light"],
|
|
47
44
|
stylePreview: false,
|
|
48
45
|
userHasExplicitlySetTheTheme: false,
|
|
49
46
|
};
|
|
@@ -60,9 +57,9 @@ const toggleDarkClass = (
|
|
|
60
57
|
current,
|
|
61
58
|
darkClass = defaultParams.darkClass,
|
|
62
59
|
lightClass = defaultParams.lightClass,
|
|
63
|
-
}: DarkModeStore
|
|
60
|
+
}: DarkModeStore,
|
|
64
61
|
) => {
|
|
65
|
-
if (current ===
|
|
62
|
+
if (current === "dark") {
|
|
66
63
|
el.classList.remove(...arrayify(lightClass));
|
|
67
64
|
el.classList.add(...arrayify(darkClass));
|
|
68
65
|
} else {
|
|
@@ -74,21 +71,19 @@ const toggleDarkClass = (
|
|
|
74
71
|
/** Coerce a string to a single item array, or return an array as-is */
|
|
75
72
|
const arrayify = (classes: string | string[]): string[] => {
|
|
76
73
|
const arr: string[] = [];
|
|
74
|
+
|
|
77
75
|
return arr.concat(classes).map((item) => item);
|
|
78
76
|
};
|
|
79
77
|
|
|
80
78
|
/** Update the preview iframe class */
|
|
81
79
|
const updatePreview = (store: DarkModeStore) => {
|
|
82
|
-
const iframe = document.getElementById(
|
|
83
|
-
'storybook-preview-iframe'
|
|
84
|
-
) as HTMLIFrameElement;
|
|
80
|
+
const iframe = document.getElementById("storybook-preview-iframe") as HTMLIFrameElement;
|
|
85
81
|
|
|
86
82
|
if (!iframe) {
|
|
87
83
|
return;
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
const iframeDocument =
|
|
91
|
-
iframe.contentDocument || iframe.contentWindow?.document;
|
|
86
|
+
const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
|
|
92
87
|
const target = iframeDocument?.querySelector<HTMLElement>(store.classTarget);
|
|
93
88
|
|
|
94
89
|
if (!target) {
|
|
@@ -110,12 +105,10 @@ const updateManager = (store: DarkModeStore) => {
|
|
|
110
105
|
};
|
|
111
106
|
|
|
112
107
|
/** Update changed dark mode settings and persist to localStorage */
|
|
113
|
-
export const store = (
|
|
114
|
-
userTheme: Partial<DarkModeStore> = {}
|
|
115
|
-
): DarkModeStore => {
|
|
108
|
+
export const store = (userTheme: Partial<DarkModeStore> = {}): DarkModeStore => {
|
|
116
109
|
const storedItem = window.localStorage.getItem(STORAGE_KEY);
|
|
117
110
|
|
|
118
|
-
if (typeof storedItem ===
|
|
111
|
+
if (typeof storedItem === "string") {
|
|
119
112
|
const stored = JSON.parse(storedItem) as DarkModeStore;
|
|
120
113
|
|
|
121
114
|
if (userTheme) {
|
|
@@ -149,39 +142,41 @@ interface DarkModeProps {
|
|
|
149
142
|
/** A toolbar icon to toggle between dark and light themes in storybook */
|
|
150
143
|
export function DarkMode({ api }: DarkModeProps) {
|
|
151
144
|
const [isDark, setDark] = React.useState(prefersDark.matches);
|
|
152
|
-
const darkModeParams = useParameter<Partial<DarkModeStore>>(
|
|
145
|
+
const darkModeParams = useParameter<Partial<DarkModeStore>>("darkMode", {});
|
|
153
146
|
const { current: defaultMode, stylePreview, ...params } = darkModeParams;
|
|
154
147
|
const channel = api.getChannel();
|
|
155
148
|
// Save custom themes on init
|
|
156
149
|
const userHasExplicitlySetTheTheme = React.useMemo(
|
|
157
150
|
() => store(params).userHasExplicitlySetTheTheme,
|
|
158
|
-
[params]
|
|
151
|
+
[params],
|
|
159
152
|
);
|
|
160
153
|
/** Set the theme in storybook, update the local state, and emit an event */
|
|
161
154
|
const setMode = React.useCallback(
|
|
162
155
|
(mode: Mode) => {
|
|
163
156
|
const currentStore = store();
|
|
157
|
+
|
|
164
158
|
api.setOptions({ theme: currentStore[mode] });
|
|
165
|
-
setDark(mode ===
|
|
166
|
-
api.getChannel().emit(DARK_MODE_EVENT_NAME, mode ===
|
|
159
|
+
setDark(mode === "dark");
|
|
160
|
+
api.getChannel().emit(DARK_MODE_EVENT_NAME, mode === "dark");
|
|
167
161
|
updateManager(currentStore);
|
|
162
|
+
|
|
168
163
|
if (stylePreview) {
|
|
169
164
|
updatePreview(currentStore);
|
|
170
165
|
}
|
|
171
166
|
},
|
|
172
|
-
[api, stylePreview]
|
|
167
|
+
[api, stylePreview],
|
|
173
168
|
);
|
|
174
169
|
|
|
175
170
|
/** Update the theme settings in localStorage, react, and storybook */
|
|
176
171
|
const updateMode = React.useCallback(
|
|
177
172
|
(mode?: Mode) => {
|
|
178
173
|
const currentStore = store();
|
|
179
|
-
const current =
|
|
180
|
-
|
|
174
|
+
const current = mode || (currentStore.current === "dark" ? "light" : "dark");
|
|
175
|
+
|
|
181
176
|
updateStore({ ...currentStore, current });
|
|
182
177
|
setMode(current);
|
|
183
178
|
},
|
|
184
|
-
[setMode]
|
|
179
|
+
[setMode],
|
|
185
180
|
);
|
|
186
181
|
|
|
187
182
|
/** Update the theme based on the color preference */
|
|
@@ -190,12 +185,13 @@ export function DarkMode({ api }: DarkModeProps) {
|
|
|
190
185
|
return;
|
|
191
186
|
}
|
|
192
187
|
|
|
193
|
-
updateMode(event.matches ?
|
|
188
|
+
updateMode(event.matches ? "dark" : "light");
|
|
194
189
|
}
|
|
195
190
|
|
|
196
191
|
/** Render the current theme */
|
|
197
192
|
const renderTheme = React.useCallback(() => {
|
|
198
|
-
const { current =
|
|
193
|
+
const { current = "light" } = store();
|
|
194
|
+
|
|
199
195
|
setMode(current);
|
|
200
196
|
}, [setMode]);
|
|
201
197
|
|
|
@@ -203,12 +199,14 @@ export function DarkMode({ api }: DarkModeProps) {
|
|
|
203
199
|
const handleIconClick = () => {
|
|
204
200
|
updateMode();
|
|
205
201
|
const currentStore = store();
|
|
202
|
+
|
|
206
203
|
updateStore({ ...currentStore, userHasExplicitlySetTheTheme: true });
|
|
207
204
|
};
|
|
208
205
|
|
|
209
206
|
/** When storybook params change update the stored themes */
|
|
210
207
|
React.useEffect(() => {
|
|
211
208
|
const currentStore = store();
|
|
209
|
+
|
|
212
210
|
// Ensure we use the stores `current` value first to persist
|
|
213
211
|
// themeing between page loads and story changes.
|
|
214
212
|
updateStore({
|
|
@@ -223,6 +221,7 @@ export function DarkMode({ api }: DarkModeProps) {
|
|
|
223
221
|
channel.on(SET_STORIES, renderTheme);
|
|
224
222
|
channel.on(DOCS_RENDERED, renderTheme);
|
|
225
223
|
prefersDark.addListener(prefersDarkUpdate);
|
|
224
|
+
|
|
226
225
|
return () => {
|
|
227
226
|
channel.removeListener(STORY_CHANGED, renderTheme);
|
|
228
227
|
channel.removeListener(SET_STORIES, renderTheme);
|
|
@@ -232,6 +231,7 @@ export function DarkMode({ api }: DarkModeProps) {
|
|
|
232
231
|
});
|
|
233
232
|
React.useEffect(() => {
|
|
234
233
|
channel.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode);
|
|
234
|
+
|
|
235
235
|
return () => {
|
|
236
236
|
channel.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode);
|
|
237
237
|
};
|
|
@@ -247,15 +247,14 @@ export function DarkMode({ api }: DarkModeProps) {
|
|
|
247
247
|
if (defaultMode) {
|
|
248
248
|
updateMode(defaultMode);
|
|
249
249
|
} else if (prefersDark.matches) {
|
|
250
|
-
updateMode(
|
|
250
|
+
updateMode("dark");
|
|
251
251
|
}
|
|
252
252
|
}, [defaultMode, updateMode, userHasExplicitlySetTheTheme]);
|
|
253
|
+
|
|
253
254
|
return (
|
|
254
255
|
<IconButton
|
|
255
256
|
key="dark-mode"
|
|
256
|
-
title={
|
|
257
|
-
isDark ? 'Change theme to light mode' : 'Change theme to dark mode'
|
|
258
|
-
}
|
|
257
|
+
title={isDark ? "Change theme to light mode" : "Change theme to dark mode"}
|
|
259
258
|
onClick={handleIconClick}
|
|
260
259
|
>
|
|
261
260
|
{isDark ? <SunIcon aria-hidden="true" /> : <MoonIcon aria-hidden="true" />}
|
package/src/constants.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const DARK_MODE_EVENT_NAME =
|
|
2
|
-
export const UPDATE_DARK_MODE_EVENT_NAME =
|
|
1
|
+
export const DARK_MODE_EVENT_NAME = "DARK_MODE";
|
|
2
|
+
export const UPDATE_DARK_MODE_EVENT_NAME = "UPDATE_DARK_MODE";
|
package/src/index.tsx
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { addons } from "storybook/preview-api";
|
|
3
|
+
import { DARK_MODE_EVENT_NAME } from "./constants";
|
|
4
|
+
import { store } from "./Tool";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Returns the current state of storybook's dark-mode
|
|
7
8
|
*/
|
|
8
9
|
export function useDarkMode(): boolean {
|
|
9
|
-
const [isDark, setIsDark] = useState(() => store().current ===
|
|
10
|
+
const [isDark, setIsDark] = useState(() => store().current === "dark");
|
|
10
11
|
|
|
11
12
|
useEffect(() => {
|
|
12
13
|
const chan = addons.getChannel();
|
|
14
|
+
|
|
13
15
|
chan.on(DARK_MODE_EVENT_NAME, setIsDark);
|
|
16
|
+
|
|
14
17
|
return () => chan.off(DARK_MODE_EVENT_NAME, setIsDark);
|
|
15
18
|
}, []);
|
|
16
19
|
|
|
17
20
|
return isDark;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
export * from
|
|
23
|
+
export * from "./constants";
|
package/src/preset/manager.tsx
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { addons } from
|
|
2
|
-
import { Addon_TypesEnum } from
|
|
3
|
-
import { themes } from
|
|
4
|
-
import * as React from
|
|
1
|
+
import { addons } from "storybook/manager-api";
|
|
2
|
+
import { Addon_TypesEnum } from "storybook/internal/types";
|
|
3
|
+
import { themes } from "storybook/theming";
|
|
4
|
+
import * as React from "react";
|
|
5
5
|
|
|
6
|
-
import Tool, { prefersDark, store } from
|
|
6
|
+
import Tool, { prefersDark, store } from "../Tool";
|
|
7
7
|
|
|
8
8
|
const currentStore = store();
|
|
9
|
-
const currentTheme =
|
|
10
|
-
currentStore.current || (prefersDark.matches && 'dark') || 'light';
|
|
9
|
+
const currentTheme = currentStore.current || (prefersDark.matches && "dark") || "light";
|
|
11
10
|
|
|
12
11
|
addons.setConfig({
|
|
13
12
|
theme: {
|
|
@@ -16,11 +15,11 @@ addons.setConfig({
|
|
|
16
15
|
},
|
|
17
16
|
});
|
|
18
17
|
|
|
19
|
-
addons.register(
|
|
20
|
-
addons.add(
|
|
21
|
-
title:
|
|
18
|
+
addons.register("storybook/dark-mode", (api) => {
|
|
19
|
+
addons.add("storybook/dark-mode", {
|
|
20
|
+
title: "dark mode",
|
|
22
21
|
type: Addon_TypesEnum.TOOL,
|
|
23
|
-
match: ({ viewMode }) => viewMode ===
|
|
22
|
+
match: ({ viewMode }) => viewMode === "story" || viewMode === "docs",
|
|
24
23
|
render: () => <Tool api={api} />,
|
|
25
24
|
});
|
|
26
25
|
});
|
package/src/preset.ts
ADDED
package/dist/cjs/Tool.js
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.DarkMode = DarkMode;
|
|
8
|
-
exports.updateStore = exports.store = exports.prefersDark = exports["default"] = void 0;
|
|
9
|
-
var React = _interopRequireWildcard(require("react"));
|
|
10
|
-
var _global = require("@storybook/global");
|
|
11
|
-
var _theming = require("storybook/theming");
|
|
12
|
-
var _components = require("storybook/internal/components");
|
|
13
|
-
var _icons = require("@storybook/icons");
|
|
14
|
-
var _coreEvents = require("storybook/internal/core-events");
|
|
15
|
-
var _managerApi = require("storybook/manager-api");
|
|
16
|
-
var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
|
|
17
|
-
var _constants = require("./constants");
|
|
18
|
-
var _excluded = ["current", "stylePreview"];
|
|
19
|
-
var _window$matchMedia;
|
|
20
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
21
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
22
|
-
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
23
|
-
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
24
|
-
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
25
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
26
|
-
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
27
|
-
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
28
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
29
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
30
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
31
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
32
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
33
|
-
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
34
|
-
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
35
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
36
|
-
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
37
|
-
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
38
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
39
|
-
var _ref = _global.global,
|
|
40
|
-
document = _ref.document,
|
|
41
|
-
window = _ref.window;
|
|
42
|
-
var modes = ['light', 'dark'];
|
|
43
|
-
var STORAGE_KEY = 'sb-addon-themes-3';
|
|
44
|
-
var prefersDark = exports.prefersDark = (_window$matchMedia = window.matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(window, '(prefers-color-scheme: dark)');
|
|
45
|
-
var defaultParams = {
|
|
46
|
-
classTarget: 'body',
|
|
47
|
-
dark: _theming.themes.dark,
|
|
48
|
-
darkClass: ['dark'],
|
|
49
|
-
light: _theming.themes.light,
|
|
50
|
-
lightClass: ['light'],
|
|
51
|
-
stylePreview: false,
|
|
52
|
-
userHasExplicitlySetTheTheme: false
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
/** Persist the dark mode settings in localStorage */
|
|
56
|
-
var updateStore = exports.updateStore = function updateStore(newStore) {
|
|
57
|
-
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(newStore));
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/** Add the light/dark class to an element */
|
|
61
|
-
var toggleDarkClass = function toggleDarkClass(el, _ref2) {
|
|
62
|
-
var current = _ref2.current,
|
|
63
|
-
_ref2$darkClass = _ref2.darkClass,
|
|
64
|
-
darkClass = _ref2$darkClass === void 0 ? defaultParams.darkClass : _ref2$darkClass,
|
|
65
|
-
_ref2$lightClass = _ref2.lightClass,
|
|
66
|
-
lightClass = _ref2$lightClass === void 0 ? defaultParams.lightClass : _ref2$lightClass;
|
|
67
|
-
if (current === 'dark') {
|
|
68
|
-
var _el$classList, _el$classList2;
|
|
69
|
-
(_el$classList = el.classList).remove.apply(_el$classList, _toConsumableArray(arrayify(lightClass)));
|
|
70
|
-
(_el$classList2 = el.classList).add.apply(_el$classList2, _toConsumableArray(arrayify(darkClass)));
|
|
71
|
-
} else {
|
|
72
|
-
var _el$classList3, _el$classList4;
|
|
73
|
-
(_el$classList3 = el.classList).remove.apply(_el$classList3, _toConsumableArray(arrayify(darkClass)));
|
|
74
|
-
(_el$classList4 = el.classList).add.apply(_el$classList4, _toConsumableArray(arrayify(lightClass)));
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
/** Coerce a string to a single item array, or return an array as-is */
|
|
79
|
-
var arrayify = function arrayify(classes) {
|
|
80
|
-
var arr = [];
|
|
81
|
-
return arr.concat(classes).map(function (item) {
|
|
82
|
-
return item;
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
/** Update the preview iframe class */
|
|
87
|
-
var updatePreview = function updatePreview(store) {
|
|
88
|
-
var _iframe$contentWindow;
|
|
89
|
-
var iframe = document.getElementById('storybook-preview-iframe');
|
|
90
|
-
if (!iframe) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
var iframeDocument = iframe.contentDocument || ((_iframe$contentWindow = iframe.contentWindow) === null || _iframe$contentWindow === void 0 ? void 0 : _iframe$contentWindow.document);
|
|
94
|
-
var target = iframeDocument === null || iframeDocument === void 0 ? void 0 : iframeDocument.querySelector(store.classTarget);
|
|
95
|
-
if (!target) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
toggleDarkClass(target, store);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/** Update the manager iframe class */
|
|
102
|
-
var updateManager = function updateManager(store) {
|
|
103
|
-
var manager = document.querySelector(store.classTarget);
|
|
104
|
-
if (!manager) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
toggleDarkClass(manager, store);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/** Update changed dark mode settings and persist to localStorage */
|
|
111
|
-
var store = exports.store = function store() {
|
|
112
|
-
var userTheme = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
113
|
-
var storedItem = window.localStorage.getItem(STORAGE_KEY);
|
|
114
|
-
if (typeof storedItem === 'string') {
|
|
115
|
-
var stored = JSON.parse(storedItem);
|
|
116
|
-
if (userTheme) {
|
|
117
|
-
if (userTheme.dark && !(0, _fastDeepEqual["default"])(stored.dark, userTheme.dark)) {
|
|
118
|
-
stored.dark = userTheme.dark;
|
|
119
|
-
updateStore(stored);
|
|
120
|
-
}
|
|
121
|
-
if (userTheme.light && !(0, _fastDeepEqual["default"])(stored.light, userTheme.light)) {
|
|
122
|
-
stored.light = userTheme.light;
|
|
123
|
-
updateStore(stored);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return stored;
|
|
127
|
-
}
|
|
128
|
-
return _objectSpread(_objectSpread({}, defaultParams), userTheme);
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
// On initial load, set the dark mode class on the manager
|
|
132
|
-
// This is needed if you're using mostly CSS overrides to styles the storybook
|
|
133
|
-
// Otherwise the default theme is set in src/preset/manager.tsx
|
|
134
|
-
updateManager(store());
|
|
135
|
-
/** A toolbar icon to toggle between dark and light themes in storybook */
|
|
136
|
-
function DarkMode(_ref3) {
|
|
137
|
-
var api = _ref3.api;
|
|
138
|
-
var _React$useState = React.useState(prefersDark.matches),
|
|
139
|
-
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
140
|
-
isDark = _React$useState2[0],
|
|
141
|
-
setDark = _React$useState2[1];
|
|
142
|
-
var darkModeParams = (0, _managerApi.useParameter)('darkMode', {});
|
|
143
|
-
var defaultMode = darkModeParams.current,
|
|
144
|
-
stylePreview = darkModeParams.stylePreview,
|
|
145
|
-
params = _objectWithoutProperties(darkModeParams, _excluded);
|
|
146
|
-
var channel = api.getChannel();
|
|
147
|
-
// Save custom themes on init
|
|
148
|
-
var userHasExplicitlySetTheTheme = React.useMemo(function () {
|
|
149
|
-
return store(params).userHasExplicitlySetTheTheme;
|
|
150
|
-
}, [params]);
|
|
151
|
-
/** Set the theme in storybook, update the local state, and emit an event */
|
|
152
|
-
var setMode = React.useCallback(function (mode) {
|
|
153
|
-
var currentStore = store();
|
|
154
|
-
api.setOptions({
|
|
155
|
-
theme: currentStore[mode]
|
|
156
|
-
});
|
|
157
|
-
setDark(mode === 'dark');
|
|
158
|
-
api.getChannel().emit(_constants.DARK_MODE_EVENT_NAME, mode === 'dark');
|
|
159
|
-
updateManager(currentStore);
|
|
160
|
-
if (stylePreview) {
|
|
161
|
-
updatePreview(currentStore);
|
|
162
|
-
}
|
|
163
|
-
}, [api, stylePreview]);
|
|
164
|
-
|
|
165
|
-
/** Update the theme settings in localStorage, react, and storybook */
|
|
166
|
-
var updateMode = React.useCallback(function (mode) {
|
|
167
|
-
var currentStore = store();
|
|
168
|
-
var current = mode || (currentStore.current === 'dark' ? 'light' : 'dark');
|
|
169
|
-
updateStore(_objectSpread(_objectSpread({}, currentStore), {}, {
|
|
170
|
-
current: current
|
|
171
|
-
}));
|
|
172
|
-
setMode(current);
|
|
173
|
-
}, [setMode]);
|
|
174
|
-
|
|
175
|
-
/** Update the theme based on the color preference */
|
|
176
|
-
function prefersDarkUpdate(event) {
|
|
177
|
-
if (userHasExplicitlySetTheTheme || defaultMode) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
updateMode(event.matches ? 'dark' : 'light');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** Render the current theme */
|
|
184
|
-
var renderTheme = React.useCallback(function () {
|
|
185
|
-
var _store = store(),
|
|
186
|
-
_store$current = _store.current,
|
|
187
|
-
current = _store$current === void 0 ? 'light' : _store$current;
|
|
188
|
-
setMode(current);
|
|
189
|
-
}, [setMode]);
|
|
190
|
-
|
|
191
|
-
/** Handle the user event and side effects */
|
|
192
|
-
var handleIconClick = function handleIconClick() {
|
|
193
|
-
updateMode();
|
|
194
|
-
var currentStore = store();
|
|
195
|
-
updateStore(_objectSpread(_objectSpread({}, currentStore), {}, {
|
|
196
|
-
userHasExplicitlySetTheTheme: true
|
|
197
|
-
}));
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
/** When storybook params change update the stored themes */
|
|
201
|
-
React.useEffect(function () {
|
|
202
|
-
var currentStore = store();
|
|
203
|
-
// Ensure we use the stores `current` value first to persist
|
|
204
|
-
// themeing between page loads and story changes.
|
|
205
|
-
updateStore(_objectSpread(_objectSpread(_objectSpread({}, currentStore), darkModeParams), {}, {
|
|
206
|
-
current: currentStore.current || darkModeParams.current
|
|
207
|
-
}));
|
|
208
|
-
renderTheme();
|
|
209
|
-
}, [darkModeParams, renderTheme]);
|
|
210
|
-
React.useEffect(function () {
|
|
211
|
-
channel.on(_coreEvents.STORY_CHANGED, renderTheme);
|
|
212
|
-
channel.on(_coreEvents.SET_STORIES, renderTheme);
|
|
213
|
-
channel.on(_coreEvents.DOCS_RENDERED, renderTheme);
|
|
214
|
-
prefersDark.addListener(prefersDarkUpdate);
|
|
215
|
-
return function () {
|
|
216
|
-
channel.removeListener(_coreEvents.STORY_CHANGED, renderTheme);
|
|
217
|
-
channel.removeListener(_coreEvents.SET_STORIES, renderTheme);
|
|
218
|
-
channel.removeListener(_coreEvents.DOCS_RENDERED, renderTheme);
|
|
219
|
-
prefersDark.removeListener(prefersDarkUpdate);
|
|
220
|
-
};
|
|
221
|
-
});
|
|
222
|
-
React.useEffect(function () {
|
|
223
|
-
channel.on(_constants.UPDATE_DARK_MODE_EVENT_NAME, updateMode);
|
|
224
|
-
return function () {
|
|
225
|
-
channel.removeListener(_constants.UPDATE_DARK_MODE_EVENT_NAME, updateMode);
|
|
226
|
-
};
|
|
227
|
-
});
|
|
228
|
-
// Storybook's first render doesn't have the global user params loaded so we
|
|
229
|
-
// need the effect to run whenever defaultMode is updated
|
|
230
|
-
React.useEffect(function () {
|
|
231
|
-
// If a users has set the mode this is respected
|
|
232
|
-
if (userHasExplicitlySetTheTheme) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
if (defaultMode) {
|
|
236
|
-
updateMode(defaultMode);
|
|
237
|
-
} else if (prefersDark.matches) {
|
|
238
|
-
updateMode('dark');
|
|
239
|
-
}
|
|
240
|
-
}, [defaultMode, updateMode, userHasExplicitlySetTheTheme]);
|
|
241
|
-
return /*#__PURE__*/React.createElement(_components.IconButton, {
|
|
242
|
-
key: "dark-mode",
|
|
243
|
-
title: isDark ? 'Change theme to light mode' : 'Change theme to dark mode',
|
|
244
|
-
onClick: handleIconClick
|
|
245
|
-
}, isDark ? /*#__PURE__*/React.createElement(_icons.SunIcon, {
|
|
246
|
-
"aria-hidden": "true"
|
|
247
|
-
}) : /*#__PURE__*/React.createElement(_icons.MoonIcon, {
|
|
248
|
-
"aria-hidden": "true"
|
|
249
|
-
}));
|
|
250
|
-
}
|
|
251
|
-
var _default = exports["default"] = DarkMode;
|
package/dist/cjs/constants.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.UPDATE_DARK_MODE_EVENT_NAME = exports.DARK_MODE_EVENT_NAME = void 0;
|
|
7
|
-
var DARK_MODE_EVENT_NAME = exports.DARK_MODE_EVENT_NAME = 'DARK_MODE';
|
|
8
|
-
var UPDATE_DARK_MODE_EVENT_NAME = exports.UPDATE_DARK_MODE_EVENT_NAME = 'UPDATE_DARK_MODE';
|
package/dist/cjs/index.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var _exportNames = {
|
|
7
|
-
useDarkMode: true
|
|
8
|
-
};
|
|
9
|
-
exports.useDarkMode = useDarkMode;
|
|
10
|
-
var _previewApi = require("storybook/preview-api");
|
|
11
|
-
var _constants = require("./constants");
|
|
12
|
-
Object.keys(_constants).forEach(function (key) {
|
|
13
|
-
if (key === "default" || key === "__esModule") return;
|
|
14
|
-
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
15
|
-
if (key in exports && exports[key] === _constants[key]) return;
|
|
16
|
-
Object.defineProperty(exports, key, {
|
|
17
|
-
enumerable: true,
|
|
18
|
-
get: function get() {
|
|
19
|
-
return _constants[key];
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
var _Tool = require("./Tool");
|
|
24
|
-
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
25
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
26
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
27
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
28
|
-
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
29
|
-
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
30
|
-
/**
|
|
31
|
-
* Returns the current state of storybook's dark-mode
|
|
32
|
-
*/
|
|
33
|
-
function useDarkMode() {
|
|
34
|
-
var _useState = (0, _previewApi.useState)(function () {
|
|
35
|
-
return (0, _Tool.store)().current === 'dark';
|
|
36
|
-
}),
|
|
37
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
38
|
-
isDark = _useState2[0],
|
|
39
|
-
setIsDark = _useState2[1];
|
|
40
|
-
(0, _previewApi.useEffect)(function () {
|
|
41
|
-
var chan = _previewApi.addons.getChannel();
|
|
42
|
-
chan.on(_constants.DARK_MODE_EVENT_NAME, setIsDark);
|
|
43
|
-
return function () {
|
|
44
|
-
return chan.off(_constants.DARK_MODE_EVENT_NAME, setIsDark);
|
|
45
|
-
};
|
|
46
|
-
}, []);
|
|
47
|
-
return isDark;
|
|
48
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _managerApi = require("storybook/manager-api");
|
|
4
|
-
var _types = require("storybook/internal/types");
|
|
5
|
-
var _theming = require("storybook/theming");
|
|
6
|
-
var React = _interopRequireWildcard(require("react"));
|
|
7
|
-
var _Tool = _interopRequireWildcard(require("../Tool"));
|
|
8
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
9
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
10
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
11
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
12
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
13
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
14
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
15
|
-
var currentStore = (0, _Tool.store)();
|
|
16
|
-
var currentTheme = currentStore.current || _Tool.prefersDark.matches && 'dark' || 'light';
|
|
17
|
-
_managerApi.addons.setConfig({
|
|
18
|
-
theme: _objectSpread(_objectSpread({}, _theming.themes[currentTheme]), currentStore[currentTheme])
|
|
19
|
-
});
|
|
20
|
-
_managerApi.addons.register('storybook/dark-mode', function (api) {
|
|
21
|
-
_managerApi.addons.add('storybook/dark-mode', {
|
|
22
|
-
title: 'dark mode',
|
|
23
|
-
type: _types.Addon_TypesEnum.TOOL,
|
|
24
|
-
match: function match(_ref) {
|
|
25
|
-
var viewMode = _ref.viewMode;
|
|
26
|
-
return viewMode === 'story' || viewMode === 'docs';
|
|
27
|
-
},
|
|
28
|
-
render: function render() {
|
|
29
|
-
return /*#__PURE__*/React.createElement(_Tool["default"], {
|
|
30
|
-
api: api
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|