diff --git a/.changeset/proud-tables-shave.md b/.changeset/proud-tables-shave.md new file mode 100644 index 0000000000..37c0822f35 --- /dev/null +++ b/.changeset/proud-tables-shave.md @@ -0,0 +1,10 @@ +--- +'@rocket.chat/storybook-dark-mode': minor +'@rocket.chat/fuselage-toastbar': patch +'@rocket.chat/fuselage-forms': patch +'@rocket.chat/onboarding-ui': patch +'@rocket.chat/fuselage': patch +'@rocket.chat/layout': patch +--- + +feat(storybook-dark-mode): Fork `storybook-dark-mode` diff --git a/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch b/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch deleted file mode 100644 index 5752c0da65..0000000000 --- a/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch +++ /dev/null @@ -1,543 +0,0 @@ -diff --git a/dist/cjs/Tool.js b/dist/cjs/Tool.js -index 53e12660b7265c5bf15591028d227f061e6b44d7..a47cfe84985afd92d347ea8e7a829d0577c0c306 100644 ---- a/dist/cjs/Tool.js -+++ b/dist/cjs/Tool.js -@@ -1,6 +1,6 @@ - "use strict"; - --function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } -+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); } - Object.defineProperty(exports, "__esModule", { - value: true - }); -@@ -8,42 +8,40 @@ exports.DarkMode = DarkMode; - exports.updateStore = exports.store = exports.prefersDark = exports["default"] = void 0; - var React = _interopRequireWildcard(require("react")); - var _global = require("@storybook/global"); --var _theming = require("@storybook/theming"); --var _components = require("@storybook/components"); -+var _theming = require("storybook/theming"); -+var _components = require("storybook/internal/components"); - var _icons = require("@storybook/icons"); --var _coreEvents = require("@storybook/core-events"); --var _managerApi = require("@storybook/manager-api"); -+var _coreEvents = require("storybook/internal/core-events"); -+var _managerApi = require("storybook/manager-api"); - var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal")); - var _constants = require("./constants"); - var _excluded = ["current", "stylePreview"]; - var _window$matchMedia; --function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } --function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } --function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } --function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } --function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } --function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } -+function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } -+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); } -+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; } -+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; } -+function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } - 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."); } --function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } --function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } --function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } --function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } --function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } --function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } --function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } --function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } -+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; } } -+function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } -+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; } -+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; } -+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; } -+function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } -+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); } -+function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } - 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."); } --function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } --function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } --function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } --function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } -+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; } } -+function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } -+function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } -+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; } - var _ref = _global.global, - document = _ref.document, - window = _ref.window; - var modes = ['light', 'dark']; - var STORAGE_KEY = 'sb-addon-themes-3'; --var prefersDark = (_window$matchMedia = window.matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(window, '(prefers-color-scheme: dark)'); --exports.prefersDark = prefersDark; -+var prefersDark = exports.prefersDark = (_window$matchMedia = window.matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(window, '(prefers-color-scheme: dark)'); - var defaultParams = { - classTarget: 'body', - dark: _theming.themes.dark, -@@ -55,12 +53,11 @@ var defaultParams = { - }; - - /** Persist the dark mode settings in localStorage */ --var updateStore = function updateStore(newStore) { -+var updateStore = exports.updateStore = function updateStore(newStore) { - window.localStorage.setItem(STORAGE_KEY, JSON.stringify(newStore)); - }; - - /** Add the light/dark class to an element */ --exports.updateStore = updateStore; - var toggleDarkClass = function toggleDarkClass(el, _ref2) { - var current = _ref2.current, - _ref2$darkClass = _ref2.darkClass, -@@ -111,7 +108,7 @@ var updateManager = function updateManager(store) { - }; - - /** Update changed dark mode settings and persist to localStorage */ --var store = function store() { -+var store = exports.store = function store() { - var userTheme = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var storedItem = window.localStorage.getItem(STORAGE_KEY); - if (typeof storedItem === 'string') { -@@ -134,7 +131,6 @@ var store = function store() { - // On initial load, set the dark mode class on the manager - // This is needed if you're using mostly CSS overrides to styles the storybook - // Otherwise the default theme is set in src/preset/manager.tsx --exports.store = store; - updateManager(store()); - /** A toolbar icon to toggle between dark and light themes in storybook */ - function DarkMode(_ref3) { -@@ -154,12 +150,13 @@ function DarkMode(_ref3) { - }, [params]); - /** Set the theme in storybook, update the local state, and emit an event */ - var setMode = React.useCallback(function (mode) { -+ var _api$getChannel; - var currentStore = store(); - api.setOptions({ - theme: currentStore[mode] - }); - setDark(mode === 'dark'); -- api.getChannel().emit(_constants.DARK_MODE_EVENT_NAME, mode === 'dark'); -+ (_api$getChannel = api.getChannel()) === null || _api$getChannel === void 0 || _api$getChannel.emit(_constants.DARK_MODE_EVENT_NAME, mode === 'dark'); - updateManager(currentStore); - if (stylePreview) { - updatePreview(currentStore); -@@ -212,21 +209,21 @@ function DarkMode(_ref3) { - renderTheme(); - }, [darkModeParams, renderTheme]); - React.useEffect(function () { -- channel.on(_coreEvents.STORY_CHANGED, renderTheme); -- channel.on(_coreEvents.SET_STORIES, renderTheme); -- channel.on(_coreEvents.DOCS_RENDERED, renderTheme); -+ channel === null || channel === void 0 || channel.on(_coreEvents.STORY_CHANGED, renderTheme); -+ channel === null || channel === void 0 || channel.on(_coreEvents.SET_STORIES, renderTheme); -+ channel === null || channel === void 0 || channel.on(_coreEvents.DOCS_RENDERED, renderTheme); - prefersDark.addListener(prefersDarkUpdate); - return function () { -- channel.removeListener(_coreEvents.STORY_CHANGED, renderTheme); -- channel.removeListener(_coreEvents.SET_STORIES, renderTheme); -- channel.removeListener(_coreEvents.DOCS_RENDERED, renderTheme); -+ channel === null || channel === void 0 || channel.removeListener(_coreEvents.STORY_CHANGED, renderTheme); -+ channel === null || channel === void 0 || channel.removeListener(_coreEvents.SET_STORIES, renderTheme); -+ channel === null || channel === void 0 || channel.removeListener(_coreEvents.DOCS_RENDERED, renderTheme); - prefersDark.removeListener(prefersDarkUpdate); - }; - }); - React.useEffect(function () { -- channel.on(_constants.UPDATE_DARK_MODE_EVENT_NAME, updateMode); -+ channel === null || channel === void 0 || channel.on(_constants.UPDATE_DARK_MODE_EVENT_NAME, updateMode); - return function () { -- channel.removeListener(_constants.UPDATE_DARK_MODE_EVENT_NAME, updateMode); -+ channel === null || channel === void 0 || channel.removeListener(_constants.UPDATE_DARK_MODE_EVENT_NAME, updateMode); - }; - }); - // Storybook's first render doesn't have the global user params loaded so we -@@ -252,5 +249,4 @@ function DarkMode(_ref3) { - "aria-hidden": "true" - })); - } --var _default = DarkMode; --exports["default"] = _default; -\ No newline at end of file -+var _default = exports["default"] = DarkMode; -\ No newline at end of file -diff --git a/dist/cjs/constants.js b/dist/cjs/constants.js -index b4d2aa8db372fc3c9be570092e45288a1fba9953..d3c7bda11c271934140847df98aed87f4a6a7556 100644 ---- a/dist/cjs/constants.js -+++ b/dist/cjs/constants.js -@@ -4,7 +4,5 @@ Object.defineProperty(exports, "__esModule", { - value: true - }); - exports.UPDATE_DARK_MODE_EVENT_NAME = exports.DARK_MODE_EVENT_NAME = void 0; --var DARK_MODE_EVENT_NAME = 'DARK_MODE'; --exports.DARK_MODE_EVENT_NAME = DARK_MODE_EVENT_NAME; --var UPDATE_DARK_MODE_EVENT_NAME = 'UPDATE_DARK_MODE'; --exports.UPDATE_DARK_MODE_EVENT_NAME = UPDATE_DARK_MODE_EVENT_NAME; -\ No newline at end of file -+var DARK_MODE_EVENT_NAME = exports.DARK_MODE_EVENT_NAME = 'DARK_MODE'; -+var UPDATE_DARK_MODE_EVENT_NAME = exports.UPDATE_DARK_MODE_EVENT_NAME = 'UPDATE_DARK_MODE'; -\ No newline at end of file -diff --git a/dist/cjs/index.js b/dist/cjs/index.js -index c0a0bf0138d2bd192a33bc139d2f10c5e92bcea1..870474d0e4156c0b50e9062b919baf2ff61b04e8 100644 ---- a/dist/cjs/index.js -+++ b/dist/cjs/index.js -@@ -7,7 +7,7 @@ var _exportNames = { - useDarkMode: true - }; - exports.useDarkMode = useDarkMode; --var _previewApi = require("@storybook/preview-api"); -+var _previewApi = require("storybook/preview-api"); - var _constants = require("./constants"); - Object.keys(_constants).forEach(function (key) { - if (key === "default" || key === "__esModule") return; -@@ -21,12 +21,12 @@ Object.keys(_constants).forEach(function (key) { - }); - }); - var _Tool = require("./Tool"); --function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } -+function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } - 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."); } --function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } --function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } --function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } --function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } -+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; } } -+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; } -+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; } } -+function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } - /** - * Returns the current state of storybook's dark-mode - */ -diff --git a/dist/cjs/preset/manager.js b/dist/cjs/preset/manager.js -index 3e3fd4cf247d3d7c5f42ee96259b186afa5d7bc2..159d2be912e8adb1bfca99512c1a4edaf12b1892 100644 ---- a/dist/cjs/preset/manager.js -+++ b/dist/cjs/preset/manager.js -@@ -1,18 +1,17 @@ - "use strict"; - --var _managerApi = require("@storybook/manager-api"); --var _types = require("@storybook/types"); --var _theming = require("@storybook/theming"); -+var _managerApi = require("storybook/manager-api"); -+var _types = require("storybook/internal/types"); -+var _theming = require("storybook/theming"); - var React = _interopRequireWildcard(require("react")); - var _Tool = _interopRequireWildcard(require("../Tool")); --function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } --function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } --function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } --function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } --function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } --function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } --function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } --function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } -+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); } -+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); } -+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; } -+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; } -+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; } -+function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } -+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); } - var currentStore = (0, _Tool.store)(); - var currentTheme = currentStore.current || _Tool.prefersDark.matches && 'dark' || 'light'; - _managerApi.addons.setConfig({ -diff --git a/dist/esm/Tool.js b/dist/esm/Tool.js -index 12b99ffbcc3002b3a9081d02db230ea6eb9990d7..e9121295fb048c2af70f6fbfe5cb88edc1814ea5 100644 ---- a/dist/esm/Tool.js -+++ b/dist/esm/Tool.js -@@ -1,30 +1,30 @@ --function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } -+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); } - var _excluded = ["current", "stylePreview"]; - var _window$matchMedia; --function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } --function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } --function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } -+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; } -+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; } -+function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } - 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."); } --function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } --function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } --function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } --function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } --function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } --function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } --function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } --function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } -+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; } } -+function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } -+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; } -+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; } -+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; } -+function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } -+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); } -+function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } - 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."); } --function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } --function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } --function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } --function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } -+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; } } -+function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } -+function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } -+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; } - import * as React from 'react'; - import { global } from '@storybook/global'; --import { themes } from '@storybook/theming'; --import { IconButton } from '@storybook/components'; -+import { themes } from 'storybook/theming'; -+import { IconButton } from 'storybook/internal/components'; - import { MoonIcon, SunIcon } from '@storybook/icons'; --import { STORY_CHANGED, SET_STORIES, DOCS_RENDERED } from '@storybook/core-events'; --import { useParameter } from '@storybook/manager-api'; -+import { STORY_CHANGED, SET_STORIES, DOCS_RENDERED } from 'storybook/internal/core-events'; -+import { useParameter } from 'storybook/manager-api'; - import equal from 'fast-deep-equal'; - import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from './constants'; - var _ref = global, -@@ -141,12 +141,13 @@ export function DarkMode(_ref3) { - }, [params]); - /** Set the theme in storybook, update the local state, and emit an event */ - var setMode = React.useCallback(function (mode) { -+ var _api$getChannel; - var currentStore = store(); - api.setOptions({ - theme: currentStore[mode] - }); - setDark(mode === 'dark'); -- api.getChannel().emit(DARK_MODE_EVENT_NAME, mode === 'dark'); -+ (_api$getChannel = api.getChannel()) === null || _api$getChannel === void 0 || _api$getChannel.emit(DARK_MODE_EVENT_NAME, mode === 'dark'); - updateManager(currentStore); - if (stylePreview) { - updatePreview(currentStore); -@@ -199,21 +200,21 @@ export function DarkMode(_ref3) { - renderTheme(); - }, [darkModeParams, renderTheme]); - React.useEffect(function () { -- channel.on(STORY_CHANGED, renderTheme); -- channel.on(SET_STORIES, renderTheme); -- channel.on(DOCS_RENDERED, renderTheme); -+ channel === null || channel === void 0 || channel.on(STORY_CHANGED, renderTheme); -+ channel === null || channel === void 0 || channel.on(SET_STORIES, renderTheme); -+ channel === null || channel === void 0 || channel.on(DOCS_RENDERED, renderTheme); - prefersDark.addListener(prefersDarkUpdate); - return function () { -- channel.removeListener(STORY_CHANGED, renderTheme); -- channel.removeListener(SET_STORIES, renderTheme); -- channel.removeListener(DOCS_RENDERED, renderTheme); -+ channel === null || channel === void 0 || channel.removeListener(STORY_CHANGED, renderTheme); -+ channel === null || channel === void 0 || channel.removeListener(SET_STORIES, renderTheme); -+ channel === null || channel === void 0 || channel.removeListener(DOCS_RENDERED, renderTheme); - prefersDark.removeListener(prefersDarkUpdate); - }; - }); - React.useEffect(function () { -- channel.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode); -+ channel === null || channel === void 0 || channel.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode); - return function () { -- channel.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode); -+ channel === null || channel === void 0 || channel.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode); - }; - }); - // Storybook's first render doesn't have the global user params loaded so we -diff --git a/dist/esm/index.js b/dist/esm/index.js -index f9fba78c0a84fc5e07fea8c9096983806874a592..7c4ee85a3d8de5a90ee3d105628f26dab443d3fb 100644 ---- a/dist/esm/index.js -+++ b/dist/esm/index.js -@@ -1,10 +1,10 @@ --function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } -+function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } - 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."); } --function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } --function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } --function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } --function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } --import { addons, useState, useEffect } from '@storybook/preview-api'; -+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; } } -+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; } -+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; } } -+function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } -+import { addons, useState, useEffect } from 'storybook/preview-api'; - import { DARK_MODE_EVENT_NAME } from './constants'; - import { store } from './Tool'; - -diff --git a/dist/esm/preset/manager.js b/dist/esm/preset/manager.js -index 4b14ca543bb350a1adc9d08521bcf2980204aab0..fbc6efc1a7a6077624d9c6446b37f55ff40a274c 100644 ---- a/dist/esm/preset/manager.js -+++ b/dist/esm/preset/manager.js -@@ -1,12 +1,12 @@ --function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } --function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } --function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } --function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } --function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } --function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } --import { addons } from '@storybook/manager-api'; --import { Addon_TypesEnum } from '@storybook/types'; --import { themes } from '@storybook/theming'; -+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); } -+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; } -+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; } -+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; } -+function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } -+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); } -+import { addons } from 'storybook/manager-api'; -+import { Addon_TypesEnum } from 'storybook/internal/types'; -+import { themes } from 'storybook/theming'; - import * as React from 'react'; - import Tool, { prefersDark, store } from '../Tool'; - var currentStore = store(); -diff --git a/dist/ts/Tool.d.ts b/dist/ts/Tool.d.ts -index 2de459fee17f7263e28c5f551c5a9fd128915566..b04ca52b0b808b314954f5e662d91f3e975cf5ad 100644 ---- a/dist/ts/Tool.d.ts -+++ b/dist/ts/Tool.d.ts -@@ -1,6 +1,6 @@ --/// --import { ThemeVars } from '@storybook/theming'; --import { API } from '@storybook/manager-api'; -+import * as React from 'react'; -+import { ThemeVars } from 'storybook/theming'; -+import { API } from 'storybook/manager-api'; - declare const modes: readonly ["light", "dark"]; - type Mode = typeof modes[number]; - interface DarkModeStore { -@@ -31,5 +31,5 @@ interface DarkModeProps { - api: API; - } - /** A toolbar icon to toggle between dark and light themes in storybook */ --export declare function DarkMode({ api }: DarkModeProps): JSX.Element; -+export declare function DarkMode({ api }: DarkModeProps): React.JSX.Element; - export default DarkMode; -diff --git a/package.json b/package.json -index ba076c2f1e90d8a0b67397b7dd37a28ab55b5401..c9618936a997a9c85286654635c5c5e0e1d96bc5 100644 ---- a/package.json -+++ b/package.json -@@ -35,12 +35,8 @@ - "release": "auto shipit" - }, - "dependencies": { -- "@storybook/components": "^8.0.0", -- "@storybook/core-events": "^8.0.0", - "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.5", -- "@storybook/manager-api": "^8.0.0", -- "@storybook/theming": "^8.0.0", - "fast-deep-equal": "^3.1.3", - "memoizerific": "^1.11.3" - }, -@@ -50,9 +46,9 @@ - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", -- "@storybook/builder-vite": "8.0.0", -- "@storybook/react": "8.0.0", -- "@storybook/react-vite": "8.0.0", -+ "@storybook/builder-vite": "^9.0.0", -+ "@storybook/react": "^9.0.0", -+ "@storybook/react-vite": "^9.0.0", - "@types/node": "^18.11.11", - "@types/react": "^18.0.26", - "@typescript-eslint/eslint-plugin": "5.45.1", -@@ -72,7 +68,7 @@ - "react": "^18.2.0", - "react-dom": "^18.2.0", - "rimraf": "^3.0.2", -- "storybook": "8.0.0", -+ "storybook": "^9.0.0", - "ts-node": "^10.9.1", - "typescript": "^4.9.3", - "vite": "^5.1.3" -@@ -83,5 +79,6 @@ - "prettier": { - "singleQuote": true - }, -- "license": "MIT" -+ "license": "MIT", -+ "packageManager": "yarn@4.9.2" - } -diff --git a/src/Tool.tsx b/src/Tool.tsx -index cdbd73447add8c0cc049de8dc36adbb1496612f6..a110a77a5c11b86db1f494321201a935e40d920c 100644 ---- a/src/Tool.tsx -+++ b/src/Tool.tsx -@@ -1,14 +1,14 @@ - import * as React from 'react'; - import { global } from '@storybook/global'; --import { themes, ThemeVars } from '@storybook/theming'; --import { IconButton } from '@storybook/components'; -+import { themes, ThemeVars } from 'storybook/theming'; -+import { IconButton } from 'storybook/internal/components'; - import { MoonIcon, SunIcon } from '@storybook/icons'; - import { - STORY_CHANGED, - SET_STORIES, - DOCS_RENDERED, --} from '@storybook/core-events'; --import { API, useParameter } from '@storybook/manager-api'; -+} from 'storybook/internal/core-events'; -+import { API, useParameter } from 'storybook/manager-api'; - import equal from 'fast-deep-equal'; - import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from './constants'; - -@@ -163,7 +163,7 @@ export function DarkMode({ api }: DarkModeProps) { - const currentStore = store(); - api.setOptions({ theme: currentStore[mode] }); - setDark(mode === 'dark'); -- api.getChannel().emit(DARK_MODE_EVENT_NAME, mode === 'dark'); -+ api.getChannel()?.emit(DARK_MODE_EVENT_NAME, mode === 'dark'); - updateManager(currentStore); - if (stylePreview) { - updatePreview(currentStore); -@@ -219,21 +219,21 @@ export function DarkMode({ api }: DarkModeProps) { - renderTheme(); - }, [darkModeParams, renderTheme]); - React.useEffect(() => { -- channel.on(STORY_CHANGED, renderTheme); -- channel.on(SET_STORIES, renderTheme); -- channel.on(DOCS_RENDERED, renderTheme); -+ channel?.on(STORY_CHANGED, renderTheme); -+ channel?.on(SET_STORIES, renderTheme); -+ channel?.on(DOCS_RENDERED, renderTheme); - prefersDark.addListener(prefersDarkUpdate); - return () => { -- channel.removeListener(STORY_CHANGED, renderTheme); -- channel.removeListener(SET_STORIES, renderTheme); -- channel.removeListener(DOCS_RENDERED, renderTheme); -+ channel?.removeListener(STORY_CHANGED, renderTheme); -+ channel?.removeListener(SET_STORIES, renderTheme); -+ channel?.removeListener(DOCS_RENDERED, renderTheme); - prefersDark.removeListener(prefersDarkUpdate); - }; - }); - React.useEffect(() => { -- channel.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode); -+ channel?.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode); - return () => { -- channel.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode); -+ channel?.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode); - }; - }); - // Storybook's first render doesn't have the global user params loaded so we -diff --git a/src/index.tsx b/src/index.tsx -index 6178cd588c88c2d1b49e96a1dff3c2277027d488..2cd168982a7255b49cc3c8e56309f5723e3e0c20 100644 ---- a/src/index.tsx -+++ b/src/index.tsx -@@ -1,4 +1,4 @@ --import { addons, useState, useEffect } from '@storybook/preview-api'; -+import { addons, useState, useEffect } from 'storybook/preview-api'; - import { DARK_MODE_EVENT_NAME } from './constants'; - import { store } from './Tool'; - -diff --git a/src/preset/manager.tsx b/src/preset/manager.tsx -index 471ec69d1548b829ac30a7359afef682c3a239d9..bc00efc8ccb85518db46d6a1afc2667b6ae05dd1 100644 ---- a/src/preset/manager.tsx -+++ b/src/preset/manager.tsx -@@ -1,6 +1,6 @@ --import { addons } from '@storybook/manager-api'; --import { Addon_TypesEnum } from '@storybook/types'; --import { themes } from '@storybook/theming'; -+import { addons } from 'storybook/manager-api'; -+import { Addon_TypesEnum } from 'storybook/internal/types'; -+import { themes } from 'storybook/theming'; - import * as React from 'react'; - - import Tool, { prefersDark, store } from '../Tool'; diff --git a/README.md b/README.md index f2f21afe5d..9db7fae7b6 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ | πŸ“¦ [`@rocket.chat/mp3-encoder`](/packages/mp3-encoder) | A LAME encoder to be used in web workers | [![npm](https://img.shields.io/npm/v/@rocket.chat/mp3-encoder?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/mp3-encoder) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/mp3-encoder?style=flat-square) | | πŸ“¦ [`@rocket.chat/onboarding-ui`](/packages/onboarding-ui) | Set of components and functions for the onboarding experience on Rocket.Chat | [![npm](https://img.shields.io/npm/v/@rocket.chat/onboarding-ui?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/onboarding-ui) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/onboarding-ui?style=flat-square) | | πŸ“¦ [`@rocket.chat/prettier-config`](/packages/prettier-config) | Prettier configuration for Rocket.Chat repositories | [![npm](https://img.shields.io/npm/v/@rocket.chat/prettier-config?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/prettier-config) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/prettier-config?style=flat-square) | +| πŸ“¦ [`@rocket.chat/storybook-dark-mode`](/packages/storybook-dark-mode) | Toggle between light and dark mode in Storybook (Rocket.Chat fork) | [![npm](https://img.shields.io/npm/v/@rocket.chat/storybook-dark-mode?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/storybook-dark-mode) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/storybook-dark-mode?style=flat-square) | | πŸ“¦ [`@rocket.chat/string-helpers`](/packages/string-helpers) | Helper functions for string manipulation | [![npm](https://img.shields.io/npm/v/@rocket.chat/string-helpers?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/string-helpers) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/string-helpers?style=flat-square) | | πŸ“¦ [`@rocket.chat/styled`](/packages/styled) | A simple styled API for React components | [![npm](https://img.shields.io/npm/v/@rocket.chat/styled?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/styled) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/styled?style=flat-square) | | πŸ“¦ [`@rocket.chat/stylis-logical-props-middleware`](/packages/stylis-logical-props-middleware) | Stylis middleware to handle CSS Logical Properties and their fallbacks | [![npm](https://img.shields.io/npm/v/@rocket.chat/stylis-logical-props-middleware?style=flat-square)](https://www.npmjs.com/package/@rocket.chat/stylis-logical-props-middleware) | ![deps](https://img.shields.io/librariesio/release/npm/@rocket.chat/stylis-logical-props-middleware?style=flat-square) | diff --git a/packages/fuselage-forms/.storybook/DocsContainer.tsx b/packages/fuselage-forms/.storybook/DocsContainer.tsx index 0b9d0661c8..1e6454ef59 100644 --- a/packages/fuselage-forms/.storybook/DocsContainer.tsx +++ b/packages/fuselage-forms/.storybook/DocsContainer.tsx @@ -1,9 +1,9 @@ +import { DARK_MODE_EVENT_NAME } from '@rocket.chat/storybook-dark-mode'; import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'; import type { ComponentPropsWithoutRef } from 'react'; import { useEffect, useState } from 'react'; import { addons } from 'storybook/preview-api'; import { themes } from 'storybook/theming'; -import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; const channel = addons.getChannel(); diff --git a/packages/fuselage-forms/.storybook/main.ts b/packages/fuselage-forms/.storybook/main.ts index 1b90a83b3a..bb4f9e307b 100644 --- a/packages/fuselage-forms/.storybook/main.ts +++ b/packages/fuselage-forms/.storybook/main.ts @@ -4,7 +4,7 @@ import type { StorybookConfig } from '@storybook/react-webpack5'; export default { addons: [ - getAbsolutePath('storybook-dark-mode'), + getAbsolutePath('@rocket.chat/storybook-dark-mode'), getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), getAbsolutePath('@storybook/addon-docs'), ], diff --git a/packages/fuselage-forms/.storybook/preview.tsx b/packages/fuselage-forms/.storybook/preview.tsx index 574f033960..2d26f6b0e1 100644 --- a/packages/fuselage-forms/.storybook/preview.tsx +++ b/packages/fuselage-forms/.storybook/preview.tsx @@ -1,9 +1,9 @@ import { PaletteStyleTag } from '@rocket.chat/fuselage'; import breakpointTokens from '@rocket.chat/fuselage-tokens/breakpoints.json'; import surface from '@rocket.chat/fuselage-tokens/dist/surface.json'; +import { useDarkMode } from '@rocket.chat/storybook-dark-mode'; import type { Preview } from '@storybook/react-webpack5'; import { themes } from 'storybook/theming'; -import { useDarkMode } from 'storybook-dark-mode'; import manifest from '../package.json'; diff --git a/packages/fuselage-forms/package.json b/packages/fuselage-forms/package.json index 40456469dc..522a5d3fe0 100644 --- a/packages/fuselage-forms/package.json +++ b/packages/fuselage-forms/package.json @@ -37,6 +37,7 @@ "devDependencies": { "@rocket.chat/fuselage": "*", "@rocket.chat/fuselage-tokens": "workspace:~", + "@rocket.chat/storybook-dark-mode": "workspace:~", "@storybook/addon-docs": "~9.1.17", "@storybook/addon-webpack5-compiler-swc": "~4.0.2", "@storybook/react-webpack5": "~9.1.17", @@ -59,7 +60,6 @@ "react-dom": "~18.3.1", "rimraf": "~6.0.1", "storybook": "~9.1.17", - "storybook-dark-mode": "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch", "ts-jest": "~29.4.6", "typescript": "~5.9.3", "webpack": "~5.102.1" diff --git a/packages/fuselage-toastbar/.storybook/DocsContainer.tsx b/packages/fuselage-toastbar/.storybook/DocsContainer.tsx index 0b9d0661c8..1e6454ef59 100644 --- a/packages/fuselage-toastbar/.storybook/DocsContainer.tsx +++ b/packages/fuselage-toastbar/.storybook/DocsContainer.tsx @@ -1,9 +1,9 @@ +import { DARK_MODE_EVENT_NAME } from '@rocket.chat/storybook-dark-mode'; import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'; import type { ComponentPropsWithoutRef } from 'react'; import { useEffect, useState } from 'react'; import { addons } from 'storybook/preview-api'; import { themes } from 'storybook/theming'; -import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; const channel = addons.getChannel(); diff --git a/packages/fuselage-toastbar/.storybook/main.ts b/packages/fuselage-toastbar/.storybook/main.ts index ec14e60ffd..a167495b54 100644 --- a/packages/fuselage-toastbar/.storybook/main.ts +++ b/packages/fuselage-toastbar/.storybook/main.ts @@ -4,7 +4,7 @@ import type { StorybookConfig } from '@storybook/react-webpack5'; const config: StorybookConfig = { addons: [ - getAbsolutePath('storybook-dark-mode'), + getAbsolutePath('@rocket.chat/storybook-dark-mode'), getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), getAbsolutePath('@storybook/addon-docs'), ], diff --git a/packages/fuselage-toastbar/.storybook/preview.tsx b/packages/fuselage-toastbar/.storybook/preview.tsx index 3ffff50be5..905c6c4cac 100644 --- a/packages/fuselage-toastbar/.storybook/preview.tsx +++ b/packages/fuselage-toastbar/.storybook/preview.tsx @@ -1,9 +1,9 @@ import surface from '@rocket.chat/fuselage-tokens/dist/surface.json'; import { DarkModeProvider } from '@rocket.chat/layout'; +import { useDarkMode } from '@rocket.chat/storybook-dark-mode'; import type { Preview } from '@storybook/react-webpack5'; import { Suspense } from 'react'; import { themes } from 'storybook/theming'; -import { useDarkMode } from 'storybook-dark-mode'; import manifest from '../package.json'; import ToastBarProvider from '../src/ToastBarProvider'; diff --git a/packages/fuselage-toastbar/package.json b/packages/fuselage-toastbar/package.json index 4b269aba14..5c127f66de 100644 --- a/packages/fuselage-toastbar/package.json +++ b/packages/fuselage-toastbar/package.json @@ -49,6 +49,7 @@ "@rocket.chat/fuselage-hooks": "workspace:~", "@rocket.chat/fuselage-tokens": "workspace:~", "@rocket.chat/layout": "workspace:~", + "@rocket.chat/storybook-dark-mode": "workspace:~", "@rocket.chat/styled": "workspace:~", "@storybook/addon-docs": "~9.1.17", "@storybook/addon-webpack5-compiler-swc": "~4.0.2", @@ -69,7 +70,6 @@ "react-dom": "~18.3.1", "rimraf": "~6.0.1", "storybook": "~9.1.17", - "storybook-dark-mode": "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch", "ts-jest": "~29.4.6", "typedoc": "~0.28.16", "typescript": "~5.9.3" diff --git a/packages/fuselage/.storybook/DocsContainer.tsx b/packages/fuselage/.storybook/DocsContainer.tsx index 0b9d0661c8..1e6454ef59 100644 --- a/packages/fuselage/.storybook/DocsContainer.tsx +++ b/packages/fuselage/.storybook/DocsContainer.tsx @@ -1,9 +1,9 @@ +import { DARK_MODE_EVENT_NAME } from '@rocket.chat/storybook-dark-mode'; import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'; import type { ComponentPropsWithoutRef } from 'react'; import { useEffect, useState } from 'react'; import { addons } from 'storybook/preview-api'; import { themes } from 'storybook/theming'; -import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; const channel = addons.getChannel(); diff --git a/packages/fuselage/.storybook/main.ts b/packages/fuselage/.storybook/main.ts index 0b10181adf..032b16d014 100644 --- a/packages/fuselage/.storybook/main.ts +++ b/packages/fuselage/.storybook/main.ts @@ -5,7 +5,7 @@ import type { StorybookConfig } from '@storybook/react-webpack5'; export default { addons: [ getAbsolutePath('@storybook/addon-a11y'), - getAbsolutePath('storybook-dark-mode'), + getAbsolutePath('@rocket.chat/storybook-dark-mode'), getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), { name: getAbsolutePath('@storybook/addon-styling-webpack'), diff --git a/packages/fuselage/.storybook/preview.tsx b/packages/fuselage/.storybook/preview.tsx index 5075022059..dfd5d65d6c 100644 --- a/packages/fuselage/.storybook/preview.tsx +++ b/packages/fuselage/.storybook/preview.tsx @@ -1,8 +1,8 @@ import breakpointTokens from '@rocket.chat/fuselage-tokens/breakpoints.json'; import surface from '@rocket.chat/fuselage-tokens/dist/surface.json'; +import { useDarkMode } from '@rocket.chat/storybook-dark-mode'; import type { Preview } from '@storybook/react-webpack5'; import { themes } from 'storybook/theming'; -import { useDarkMode } from 'storybook-dark-mode'; import manifest from '../package.json'; import { PaletteStyleTag } from '../src'; diff --git a/packages/fuselage/package.json b/packages/fuselage/package.json index 07897335db..937a0799ec 100644 --- a/packages/fuselage/package.json +++ b/packages/fuselage/package.json @@ -54,6 +54,7 @@ "@babel/preset-react": "~7.27.1", "@rocket.chat/fuselage-hooks": "workspace:~", "@rocket.chat/icons": "workspace:~", + "@rocket.chat/storybook-dark-mode": "workspace:~", "@storybook/addon-a11y": "~9.1.17", "@storybook/addon-docs": "~9.1.17", "@storybook/addon-links": "~9.1.17", @@ -97,7 +98,6 @@ "sass": "~1.93.3", "sass-loader": "~16.0.6", "storybook": "~9.1.17", - "storybook-dark-mode": "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch", "style-loader": "~4.0.0", "stylelint": "~16.25.0", "stylelint-order": "~7.0.1", diff --git a/packages/layout/.storybook/DocsContainer.tsx b/packages/layout/.storybook/DocsContainer.tsx index 0b9d0661c8..1e6454ef59 100644 --- a/packages/layout/.storybook/DocsContainer.tsx +++ b/packages/layout/.storybook/DocsContainer.tsx @@ -1,9 +1,9 @@ +import { DARK_MODE_EVENT_NAME } from '@rocket.chat/storybook-dark-mode'; import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'; import type { ComponentPropsWithoutRef } from 'react'; import { useEffect, useState } from 'react'; import { addons } from 'storybook/preview-api'; import { themes } from 'storybook/theming'; -import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; const channel = addons.getChannel(); diff --git a/packages/layout/.storybook/main.ts b/packages/layout/.storybook/main.ts index 6e21538f3c..970b463d0e 100644 --- a/packages/layout/.storybook/main.ts +++ b/packages/layout/.storybook/main.ts @@ -4,7 +4,7 @@ import type { StorybookConfig } from '@storybook/react-webpack5'; export default { addons: [ - getAbsolutePath('storybook-dark-mode'), + getAbsolutePath('@rocket.chat/storybook-dark-mode'), getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), getAbsolutePath('@storybook/addon-a11y'), getAbsolutePath('@storybook/addon-docs'), diff --git a/packages/layout/.storybook/preview.tsx b/packages/layout/.storybook/preview.tsx index d67c8e5f22..6dd1d90ae7 100644 --- a/packages/layout/.storybook/preview.tsx +++ b/packages/layout/.storybook/preview.tsx @@ -1,9 +1,9 @@ import { PaletteStyleTag } from '@rocket.chat/fuselage'; import surface from '@rocket.chat/fuselage-tokens/dist/surface.json'; +import { useDarkMode } from '@rocket.chat/storybook-dark-mode'; import type { Preview } from '@storybook/react-webpack5'; import { Suspense } from 'react'; import { themes } from 'storybook/theming'; -import { useDarkMode } from 'storybook-dark-mode'; import manifest from '../package.json'; import DarkModeProvider from '../src/DarkModeProvider'; diff --git a/packages/layout/package.json b/packages/layout/package.json index bbdf759539..8b1340ddb7 100644 --- a/packages/layout/package.json +++ b/packages/layout/package.json @@ -37,6 +37,7 @@ "devDependencies": { "@rocket.chat/fuselage": "workspace:~", "@rocket.chat/fuselage-tokens": "workspace:~", + "@rocket.chat/storybook-dark-mode": "workspace:~", "@storybook/addon-a11y": "~9.1.17", "@storybook/addon-docs": "~9.1.17", "@storybook/addon-webpack5-compiler-swc": "~4.0.2", @@ -57,7 +58,6 @@ "react-i18next": "~13.2.2", "rimraf": "~6.0.1", "storybook": "~9.1.17", - "storybook-dark-mode": "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch", "ts-jest": "~29.4.6", "typedoc": "~0.28.16", "typescript": "~5.9.3" diff --git a/packages/onboarding-ui/.storybook/DocsContainer.tsx b/packages/onboarding-ui/.storybook/DocsContainer.tsx index 0b9d0661c8..1e6454ef59 100644 --- a/packages/onboarding-ui/.storybook/DocsContainer.tsx +++ b/packages/onboarding-ui/.storybook/DocsContainer.tsx @@ -1,9 +1,9 @@ +import { DARK_MODE_EVENT_NAME } from '@rocket.chat/storybook-dark-mode'; import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'; import type { ComponentPropsWithoutRef } from 'react'; import { useEffect, useState } from 'react'; import { addons } from 'storybook/preview-api'; import { themes } from 'storybook/theming'; -import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; const channel = addons.getChannel(); diff --git a/packages/onboarding-ui/.storybook/main.ts b/packages/onboarding-ui/.storybook/main.ts index 2543b1a6e9..bd9186d721 100644 --- a/packages/onboarding-ui/.storybook/main.ts +++ b/packages/onboarding-ui/.storybook/main.ts @@ -5,7 +5,7 @@ import type { StorybookConfig } from '@storybook/react-webpack5'; export default { addons: [ getAbsolutePath('@storybook/addon-a11y'), - getAbsolutePath('storybook-dark-mode'), + getAbsolutePath('@rocket.chat/storybook-dark-mode'), getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), getAbsolutePath('@storybook/addon-docs'), ], diff --git a/packages/onboarding-ui/.storybook/preview.tsx b/packages/onboarding-ui/.storybook/preview.tsx index 52275813e0..4d48ce6966 100644 --- a/packages/onboarding-ui/.storybook/preview.tsx +++ b/packages/onboarding-ui/.storybook/preview.tsx @@ -1,12 +1,12 @@ import { PaletteStyleTag } from '@rocket.chat/fuselage'; import surface from '@rocket.chat/fuselage-tokens/dist/surface.json'; import { DarkModeProvider } from '@rocket.chat/layout'; +import { useDarkMode } from '@rocket.chat/storybook-dark-mode'; import type { Preview } from '@storybook/react-webpack5'; import i18next from 'i18next'; import { Suspense } from 'react'; import { I18nextProvider, initReactI18next } from 'react-i18next'; import { themes } from 'storybook/theming'; -import { useDarkMode } from 'storybook-dark-mode'; import manifest from '../package.json'; diff --git a/packages/onboarding-ui/package.json b/packages/onboarding-ui/package.json index a760aaa746..371a8dde65 100644 --- a/packages/onboarding-ui/package.json +++ b/packages/onboarding-ui/package.json @@ -48,6 +48,7 @@ "@rocket.chat/icons": "workspace:~", "@rocket.chat/layout": "workspace:~", "@rocket.chat/logo": "workspace:~", + "@rocket.chat/storybook-dark-mode": "workspace:~", "@rocket.chat/styled": "workspace:~", "@storybook/addon-a11y": "~9.1.17", "@storybook/addon-docs": "~9.1.17", @@ -69,7 +70,6 @@ "react-i18next": "~13.2.2", "rimraf": "~6.0.1", "storybook": "~9.1.17", - "storybook-dark-mode": "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch", "ts-jest": "~29.4.6", "typedoc": "~0.28.16", "typescript": "~5.9.3" diff --git a/packages/storybook-dark-mode/.gitignore b/packages/storybook-dark-mode/.gitignore new file mode 100644 index 0000000000..9b1c8b133c --- /dev/null +++ b/packages/storybook-dark-mode/.gitignore @@ -0,0 +1 @@ +/dist diff --git a/packages/storybook-dark-mode/LICENSE b/packages/storybook-dark-mode/LICENSE new file mode 100644 index 0000000000..bb150705f2 --- /dev/null +++ b/packages/storybook-dark-mode/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2019 Andrew Lisowski +Copyright (c) 2026 Rocket.Chat Technologies Corp. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/storybook-dark-mode/README.md b/packages/storybook-dark-mode/README.md new file mode 100644 index 0000000000..f372d1ea32 --- /dev/null +++ b/packages/storybook-dark-mode/README.md @@ -0,0 +1,331 @@ +# storybook-dark-mode + +A storybook addons that lets your users toggle between dark and light mode. + +![Example](./example.gif) + +## Installation + +Install the following npm module: + +```sh +npm i --save-dev storybook-dark-mode +``` + +or with yarn: + +```sh +yarn add -D storybook-dark-mode +``` + +Then, add following content to `.storybook/main.js` + +```js +module.exports = { + addons: ['storybook-dark-mode'], +}; +``` + +## Upgrade from earlier version + +Change in `.storybook/main.js` + +```diff +module.exports = { +- addons: ['storybook-dark-mode/register'] ++ addons: ['storybook-dark-mode'] +}; +``` + +## Configuration + +Configure the dark and light mode by adding the following to your `.storybook/preview.js` file: + +```js +import { themes } from '@storybook/theming'; + +export const parameters = { + darkMode: { + // Override the default dark theme + dark: { ...themes.dark, appBg: 'black' }, + // Override the default light theme + light: { ...themes.normal, appBg: 'red' }, + }, +}; +``` + +### Default Theme + +Order of precedence for the initial color scheme: + +1. If the user has previously set a color theme it's used +2. The value you have configured for `current` parameter in your storybook +3. The OS color scheme preference + +Once the initial color scheme has been set, subsequent reloads will use this value. +To clear the cached color scheme you have to `localStorage.clear()` in the chrome console. + +```js +export const parameters = { + darkMode: { + // Set the initial theme + current: 'light', + }, +}; +``` + +### Dark/Light Class + +This plugin will apply a dark and light class name to the manager. +This allows you to easily write dark mode aware theme overrides for the storybook UI. + +You can override the classNames applied when switching between light and dark mode using the `darkClass` and `lightClass` parameters. + +```js +export const parameters = { + darkMode: { + darkClass: 'lights-out', + lightClass: 'lights-on', + }, +}; +``` + +You can also pass an array to apply multiple classes. + +```js +export const parameters = { + darkMode: { + darkClass: ['lights-out', 'foo'], + lightClass: ['lights-on', 'bar'], + }, +}; +``` + +### Preview class target + +This plugin will apply the dark/light class to the `` element of the preview iframe. This can be configured with the `classTarget` parameter. +The value will be passed to a `querySelector()` inside the iframe. + +This is useful if the `` is styled according to a parent's class, in that case it can be set to `html`. + +```js +export const parameters = { + darkMode: { + classTarget: 'html', + }, +}; +``` + +## Story integration + +### Preview ClassName + +This plugin will apply the `darkClass` and `lightClass` classes to the preview iframe if you turn on the `stylePreview` option. + +```js +export const parameters = { + darkMode: { + stylePreview: true, + }, +}; +``` + +### React + +If your components use a custom Theme provider, you can integrate it by using the provided hook. + +```js +import { useDarkMode } from 'storybook-dark-mode'; +import { addDecorator } from '@storybook/react'; + +// your theme provider +import ThemeContext from './theme'; + +// create a component that uses the dark mode hook +function ThemeWrapper(props) { + // render your custom theme provider + return ( + + {props.children} + + ); +} + +export const decorators = [renderStory => {renderStory()})]; +``` + +#### Theme Knobs + +If you want to have you UI's dark mode separate from you components' dark mode, implement this global decorator: + +```js +import { themes } from '@storybook/theming'; + +// Add a global decorator that will render a dark background when the +// "Color Scheme" knob is set to dark +const knobDecorator = (storyFn) => { + // A knob for color scheme added to every story + const colorScheme = select('Color Scheme', ['light', 'dark'], 'light'); + + // Hook your theme provider with some knobs + return React.createElement(ThemeProvider, { + // A knob for theme added to every story + theme: select('Theme', Object.keys(themes), 'default'), + colorScheme, + children: [ + React.createElement('style', { + dangerouslySetInnerHTML: { + __html: `html { ${ + colorScheme === 'dark' ? 'background-color: rgb(35,35,35);' : '' + } }`, + }, + }), + storyFn(), + ], + }); +}; + +export const decorators = [knobDecorator]; +``` + +### Events + +You can also listen for the `DARK_MODE` event via the addons channel. + +```js +import { addons } from '@storybook/preview-api'; +import { addDecorator } from '@storybook/react'; +import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; + +// your theme provider +import ThemeContext from './theme'; + +// get channel to listen to event emitter +const channel = addons.getChannel(); + +// create a component that listens for the DARK_MODE event +function ThemeWrapper(props) { + // this example uses hook but you can also use class component as well + const [isDark, setDark] = useState(false); + + useEffect(() => { + // listen to DARK_MODE event + channel.on(DARK_MODE_EVENT_NAME, setDark); + return () => channel.off(DARK_MODE_EVENT_NAME, setDark); + }, [channel, setDark]); + + // render your custom theme provider + return ( + + {props.children} + + ); +} + +export const decorators = [renderStory => {renderStory()})]; +``` + +Since in docs mode, Storybook will not display its toolbar, +You can also trigger the `UPDATE_DARK_MODE` event via the addons channel if you want to control that option in docs mode, +By editing your `.storybook/preview.js`. + +```js +import React from 'react'; +import { addons } from '@storybook/preview-api'; +import { DocsContainer } from '@storybook/addon-docs'; +import { themes } from '@storybook/theming'; + +import { + DARK_MODE_EVENT_NAME, + UPDATE_DARK_MODE_EVENT_NAME, +} from 'storybook-dark-mode'; + +const channel = addons.getChannel(); + +export const parameters = { + darkMode: { + current: 'light', + dark: { ...themes.dark }, + light: { ...themes.light }, + }, + docs: { + container: (props) => { + const [isDark, setDark] = React.useState(); + + const onChangeHandler = () => { + channel.emit(UPDATE_DARK_MODE_EVENT_NAME); + }; + + React.useEffect(() => { + channel.on(DARK_MODE_EVENT_NAME, setDark); + return () => channel.removeListener(DARK_MODE_EVENT_NAME, setDark); + }, [channel, setDark]); + + return ( +
+ + +
+ ); + }, + }, +}; +``` + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Andrew Lisowski

πŸ’¬ πŸ’» 🎨 πŸ“– πŸ€” πŸš‡ 🚧 πŸ’‘

Erik Hughes

πŸ’»

Adam Jahnke

πŸ’»

Carles NΓΊΓ±ez

πŸ’»

Adam Dierkens

πŸ’»

Tobias Skarhed

πŸ’» πŸ“–

Fatih Kalifa

πŸ’»

Jacob Coughenour

πŸ’»

Jeroen Zwartepoorte

πŸ“– πŸ’»

Alex Khomenko

πŸ’»

Paul Fasola

πŸ“–

Pavel Keyzik

πŸ“–

David Richolm

πŸ“– πŸ’»

Klaus NygΓ₯rd

πŸ’»

Arturo Silva

πŸ“– πŸ’»

Nikki Pantony

πŸ“– πŸ’»

Ian VanSchooten

πŸ’»

Fabien

πŸ“– πŸ’»

nilscox

πŸ’»

Jack Westbrook

πŸ’»

Ryan McHenry

πŸ“– πŸ’»

Clay Risser

πŸ“– πŸ’»

BeltrΓ‘n Rengifo

πŸ’»

erik-d

πŸ“–

Christopher Dura

πŸ“– πŸ’»

An Dang

πŸ’»

Zeno Jiricek

πŸ’»

Steven Sacks

πŸ“– πŸš‡ πŸ’»

Rohan Poojary

πŸ“– πŸš‡ πŸ’»

Lauri Luotola

πŸ’‘ πŸ’»

Adam GoΕ‚Δ…b

πŸ’»
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! diff --git a/packages/storybook-dark-mode/package.json b/packages/storybook-dark-mode/package.json new file mode 100644 index 0000000000..53abea5f95 --- /dev/null +++ b/packages/storybook-dark-mode/package.json @@ -0,0 +1,45 @@ +{ + "name": "@rocket.chat/storybook-dark-mode", + "version": "4.0.2", + "description": "Toggle between light and dark mode in Storybook (Rocket.Chat fork)", + "repository": { + "type": "git", + "url": "git+https://github.com/RocketChat/fuselage.git", + "directory": "packages/storybook-dark-mode" + }, + "license": "MIT", + "author": "Andrew Lisowski ", + "contributors": [ + "Rocket.Chat Technologies Corp." + ], + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", + "types": "dist/ts/index.d.ts", + "files": [ + "src", + "dist", + "preset.js" + ], + "scripts": { + "build": "rimraf dist && tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && tsc -p tsconfig.build.json", + "lint": "lint", + "lint-and-fix": "lint-and-fix" + }, + "dependencies": { + "@storybook/global": "~5.0.0", + "@storybook/icons": "~1.2.12", + "fast-deep-equal": "~3.1.3" + }, + "devDependencies": { + "@types/react": "~18.3.17", + "eslint": "~9.39.2", + "lint-all": "workspace:~", + "prettier": "~3.6.2", + "rimraf": "~6.0.1", + "typescript": "~5.9.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } +} diff --git a/packages/storybook-dark-mode/preset.js b/packages/storybook-dark-mode/preset.js new file mode 100644 index 0000000000..ef012bd3e0 --- /dev/null +++ b/packages/storybook-dark-mode/preset.js @@ -0,0 +1,7 @@ +function managerEntries(entry = []) { + return [...entry, require.resolve('./dist/esm/preset/manager')]; +} + +module.exports = { + managerEntries, +}; diff --git a/packages/storybook-dark-mode/src/Tool.tsx b/packages/storybook-dark-mode/src/Tool.tsx new file mode 100644 index 0000000000..a65b302f81 --- /dev/null +++ b/packages/storybook-dark-mode/src/Tool.tsx @@ -0,0 +1,272 @@ +import { global } from '@storybook/global'; +import { MoonIcon, SunIcon } from '@storybook/icons'; +import equal from 'fast-deep-equal'; +import * as React from 'react'; +import { IconButton } from 'storybook/internal/components'; +import { + STORY_CHANGED, + SET_STORIES, + DOCS_RENDERED, +} from 'storybook/internal/core-events'; +import type { API } from 'storybook/manager-api'; +import { useParameter } from 'storybook/manager-api'; +import type { ThemeVars } from 'storybook/theming'; +import { themes } from 'storybook/theming'; + +import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from './constants'; + +const { document, window } = global as { document: Document; window: Window }; +type Mode = 'light' | 'dark'; + +interface DarkModeStore { + /** The class target in the preview iframe */ + classTarget: string; + /** The current mode the storybook is set to */ + current: Mode; + /** The dark theme for storybook */ + dark: ThemeVars; + /** The dark class name for the preview iframe */ + darkClass: string | string[]; + /** The light theme for storybook */ + light: ThemeVars; + /** The light class name for the preview iframe */ + lightClass: string | string[]; + /** Apply mode to iframe */ + stylePreview: boolean; + /** Persist if the user has set the theme */ + userHasExplicitlySetTheTheme: boolean; +} + +const STORAGE_KEY = 'sb-addon-themes-3'; +export const prefersDark = window.matchMedia?.('(prefers-color-scheme: dark)'); + +const defaultParams: Required> = { + classTarget: 'body', + dark: themes.dark, + darkClass: ['dark'], + light: themes.light, + lightClass: ['light'], + stylePreview: false, + userHasExplicitlySetTheTheme: false, +}; + +/** Persist the dark mode settings in localStorage */ +export const updateStore = (newStore: DarkModeStore) => { + window.localStorage.setItem(STORAGE_KEY, JSON.stringify(newStore)); +}; + +/** Add the light/dark class to an element */ +const toggleDarkClass = ( + el: Element, + { + current, + darkClass = defaultParams.darkClass, + lightClass = defaultParams.lightClass, + }: DarkModeStore, +) => { + if (current === 'dark') { + el.classList.remove(...arrayify(lightClass)); + el.classList.add(...arrayify(darkClass)); + } else { + el.classList.remove(...arrayify(darkClass)); + el.classList.add(...arrayify(lightClass)); + } +}; + +/** Coerce a string to a single item array, or return an array as-is */ +const arrayify = (classes: string | string[]): string[] => { + const arr: string[] = []; + return arr.concat(classes).map((item) => item); +}; + +/** Update the preview iframe class */ +const updatePreview = (store: DarkModeStore) => { + const iframe = document.getElementById( + 'storybook-preview-iframe', + ) as HTMLIFrameElement; + + if (!iframe) { + return; + } + + const iframeDocument = + iframe.contentDocument || iframe.contentWindow?.document; + const target = iframeDocument?.querySelector(store.classTarget); + + if (!target) { + return; + } + + toggleDarkClass(target, store); +}; + +/** Update the manager iframe class */ +const updateManager = (store: DarkModeStore) => { + const manager = document.querySelector(store.classTarget); + + if (!manager) { + return; + } + + toggleDarkClass(manager, store); +}; + +/** Update changed dark mode settings and persist to localStorage */ +export const store = ( + userTheme: Partial = {}, +): DarkModeStore => { + const storedItem = window.localStorage.getItem(STORAGE_KEY); + + if (typeof storedItem === 'string') { + const stored = JSON.parse(storedItem) as DarkModeStore; + + if (userTheme) { + if (userTheme.dark && !equal(stored.dark, userTheme.dark)) { + stored.dark = userTheme.dark; + updateStore(stored); + } + + if (userTheme.light && !equal(stored.light, userTheme.light)) { + stored.light = userTheme.light; + updateStore(stored); + } + } + + return stored; + } + + return { ...defaultParams, ...userTheme } as DarkModeStore; +}; + +// On initial load, set the dark mode class on the manager +// This is needed if you're using mostly CSS overrides to styles the storybook +// Otherwise the default theme is set in src/preset/manager.tsx +updateManager(store()); + +interface DarkModeProps { + /** The storybook API */ + api: API; +} + +/** A toolbar icon to toggle between dark and light themes in storybook */ +export function DarkMode({ api }: DarkModeProps) { + const [isDark, setDark] = React.useState(prefersDark.matches); + const darkModeParams = useParameter>('darkMode', {}); + const { current: defaultMode, stylePreview, ...params } = darkModeParams; + const channel = api.getChannel(); + // Save custom themes on init + const userHasExplicitlySetTheTheme = React.useMemo( + () => store(params).userHasExplicitlySetTheTheme, + [params], + ); + /** Set the theme in storybook, update the local state, and emit an event */ + const setMode = React.useCallback( + (mode: Mode) => { + const currentStore = store(); + api.setOptions({ theme: currentStore[mode] }); + setDark(mode === 'dark'); + api.getChannel()?.emit(DARK_MODE_EVENT_NAME, mode === 'dark'); + updateManager(currentStore); + if (stylePreview) { + updatePreview(currentStore); + } + }, + [api, stylePreview], + ); + + /** Update the theme settings in localStorage, react, and storybook */ + const updateMode = React.useCallback( + (mode?: Mode) => { + const currentStore = store(); + const current = + mode || (currentStore.current === 'dark' ? 'light' : 'dark'); + updateStore({ ...currentStore, current }); + setMode(current); + }, + [setMode], + ); + + /** Update the theme based on the color preference */ + function prefersDarkUpdate(event: MediaQueryListEvent) { + if (userHasExplicitlySetTheTheme || defaultMode) { + return; + } + + updateMode(event.matches ? 'dark' : 'light'); + } + + /** Render the current theme */ + const renderTheme = React.useCallback(() => { + const { current = 'light' } = store(); + setMode(current); + }, [setMode]); + + /** Handle the user event and side effects */ + const handleIconClick = () => { + updateMode(); + const currentStore = store(); + updateStore({ ...currentStore, userHasExplicitlySetTheTheme: true }); + }; + + /** When storybook params change update the stored themes */ + React.useEffect(() => { + const currentStore = store(); + // Ensure we use the stores `current` value first to persist + // themeing between page loads and story changes. + updateStore({ + ...currentStore, + ...darkModeParams, + current: currentStore.current || darkModeParams.current, + }); + renderTheme(); + }, [darkModeParams, renderTheme]); + React.useEffect(() => { + channel?.on(STORY_CHANGED, renderTheme); + channel?.on(SET_STORIES, renderTheme); + channel?.on(DOCS_RENDERED, renderTheme); + prefersDark.addListener(prefersDarkUpdate); + return () => { + channel?.removeListener(STORY_CHANGED, renderTheme); + channel?.removeListener(SET_STORIES, renderTheme); + channel?.removeListener(DOCS_RENDERED, renderTheme); + prefersDark.removeListener(prefersDarkUpdate); + }; + }); + React.useEffect(() => { + channel?.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode); + return () => { + channel?.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode); + }; + }); + // Storybook's first render doesn't have the global user params loaded so we + // need the effect to run whenever defaultMode is updated + React.useEffect(() => { + // If a users has set the mode this is respected + if (userHasExplicitlySetTheTheme) { + return; + } + + if (defaultMode) { + updateMode(defaultMode); + } else if (prefersDark.matches) { + updateMode('dark'); + } + }, [defaultMode, updateMode, userHasExplicitlySetTheTheme]); + return ( + + {isDark ? ( + + ); +} + +export default DarkMode; diff --git a/packages/storybook-dark-mode/src/constants.ts b/packages/storybook-dark-mode/src/constants.ts new file mode 100644 index 0000000000..a2325e6a76 --- /dev/null +++ b/packages/storybook-dark-mode/src/constants.ts @@ -0,0 +1,2 @@ +export const DARK_MODE_EVENT_NAME = 'DARK_MODE'; +export const UPDATE_DARK_MODE_EVENT_NAME = 'UPDATE_DARK_MODE'; diff --git a/packages/storybook-dark-mode/src/index.tsx b/packages/storybook-dark-mode/src/index.tsx new file mode 100644 index 0000000000..0f8a73009b --- /dev/null +++ b/packages/storybook-dark-mode/src/index.tsx @@ -0,0 +1,21 @@ +import { addons, useState, useEffect } from 'storybook/preview-api'; + +import { store } from './Tool'; +import { DARK_MODE_EVENT_NAME } from './constants'; + +/** + * Returns the current state of storybook's dark-mode + */ +export function useDarkMode(): boolean { + const [isDark, setIsDark] = useState(store().current === 'dark'); + + useEffect(() => { + const chan = addons.getChannel(); + chan.on(DARK_MODE_EVENT_NAME, setIsDark); + return () => chan.off(DARK_MODE_EVENT_NAME, setIsDark); + }, []); + + return isDark; +} + +export * from './constants'; diff --git a/packages/storybook-dark-mode/src/preset/manager.tsx b/packages/storybook-dark-mode/src/preset/manager.tsx new file mode 100644 index 0000000000..daa86ed9cb --- /dev/null +++ b/packages/storybook-dark-mode/src/preset/manager.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { Addon_TypesEnum } from 'storybook/internal/types'; +import { addons } from 'storybook/manager-api'; +import { themes } from 'storybook/theming'; + +import Tool, { prefersDark, store } from '../Tool'; + +const currentStore = store(); +const currentTheme = + currentStore.current || (prefersDark.matches && 'dark') || 'light'; + +addons.setConfig({ + theme: { + ...themes[currentTheme], + ...currentStore[currentTheme], + }, +}); + +addons.register('storybook/dark-mode', (api) => { + addons.add('storybook/dark-mode', { + title: 'dark mode', + type: Addon_TypesEnum.TOOL, + match: ({ viewMode }) => viewMode === 'story' || viewMode === 'docs', + render: () => , + }); +}); diff --git a/packages/storybook-dark-mode/tsconfig.build.json b/packages/storybook-dark-mode/tsconfig.build.json new file mode 100644 index 0000000000..7a8bc30f47 --- /dev/null +++ b/packages/storybook-dark-mode/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "removeComments": false, + "outDir": "./dist/ts", + "rootDir": "./src" + }, + "exclude": ["node_modules", "dist", "**/*.spec.*", "**/*.stories*"] +} diff --git a/packages/storybook-dark-mode/tsconfig.cjs.json b/packages/storybook-dark-mode/tsconfig.cjs.json new file mode 100644 index 0000000000..765769c54f --- /dev/null +++ b/packages/storybook-dark-mode/tsconfig.cjs.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "outDir": "./dist/cjs", + "rootDir": "./src" + }, + "exclude": ["node_modules", "dist", "**/*.spec.*", "**/*.stories*"] +} diff --git a/packages/storybook-dark-mode/tsconfig.esm.json b/packages/storybook-dark-mode/tsconfig.esm.json new file mode 100644 index 0000000000..bd4630f17e --- /dev/null +++ b/packages/storybook-dark-mode/tsconfig.esm.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "outDir": "./dist/esm", + "rootDir": "./src" + }, + "exclude": ["node_modules", "dist", "**/*.spec.*", "**/*.stories*"] +} diff --git a/packages/storybook-dark-mode/tsconfig.json b/packages/storybook-dark-mode/tsconfig.json new file mode 100644 index 0000000000..1365285102 --- /dev/null +++ b/packages/storybook-dark-mode/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "target": "ES2020", + "jsx": "react", + "lib": ["ES2020", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "esModuleInterop": true, + "isolatedModules": false, + "types": ["node"] + }, + "include": ["src/**/*"] +} diff --git a/yarn.lock b/yarn.lock index 2fa2b6404f..9f00aa8dcb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5441,6 +5441,7 @@ __metadata: "@rocket.chat/emitter": "workspace:~" "@rocket.chat/fuselage": "npm:*" "@rocket.chat/fuselage-tokens": "workspace:~" + "@rocket.chat/storybook-dark-mode": "workspace:~" "@storybook/addon-docs": "npm:~9.1.17" "@storybook/addon-webpack5-compiler-swc": "npm:~4.0.2" "@storybook/react-webpack5": "npm:~9.1.17" @@ -5464,7 +5465,6 @@ __metadata: react-dom: "npm:~18.3.1" rimraf: "npm:~6.0.1" storybook: "npm:~9.1.17" - storybook-dark-mode: "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch" ts-jest: "npm:~29.4.6" typescript: "npm:~5.9.3" webpack: "npm:~5.102.1" @@ -5551,6 +5551,7 @@ __metadata: "@rocket.chat/fuselage-hooks": "workspace:~" "@rocket.chat/fuselage-tokens": "workspace:~" "@rocket.chat/layout": "workspace:~" + "@rocket.chat/storybook-dark-mode": "workspace:~" "@rocket.chat/styled": "workspace:~" "@storybook/addon-docs": "npm:~9.1.17" "@storybook/addon-webpack5-compiler-swc": "npm:~4.0.2" @@ -5572,7 +5573,6 @@ __metadata: react-timing-hooks: "npm:~4.0.2" rimraf: "npm:~6.0.1" storybook: "npm:~9.1.17" - storybook-dark-mode: "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch" ts-jest: "npm:~29.4.6" typedoc: "npm:~0.28.16" typescript: "npm:~5.9.3" @@ -5620,6 +5620,7 @@ __metadata: "@rocket.chat/fuselage-tokens": "workspace:~" "@rocket.chat/icons": "workspace:~" "@rocket.chat/memo": "workspace:~" + "@rocket.chat/storybook-dark-mode": "workspace:~" "@rocket.chat/styled": "workspace:~" "@storybook/addon-a11y": "npm:~9.1.17" "@storybook/addon-docs": "npm:~9.1.17" @@ -5668,7 +5669,6 @@ __metadata: sass: "npm:~1.93.3" sass-loader: "npm:~16.0.6" storybook: "npm:~9.1.17" - storybook-dark-mode: "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch" style-loader: "npm:~4.0.0" stylelint: "npm:~16.25.0" stylelint-order: "npm:~7.0.1" @@ -5713,6 +5713,7 @@ __metadata: dependencies: "@rocket.chat/fuselage": "workspace:~" "@rocket.chat/fuselage-tokens": "workspace:~" + "@rocket.chat/storybook-dark-mode": "workspace:~" "@storybook/addon-a11y": "npm:~9.1.17" "@storybook/addon-docs": "npm:~9.1.17" "@storybook/addon-webpack5-compiler-swc": "npm:~4.0.2" @@ -5733,7 +5734,6 @@ __metadata: react-i18next: "npm:~13.2.2" rimraf: "npm:~6.0.1" storybook: "npm:~9.1.17" - storybook-dark-mode: "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch" ts-jest: "npm:~29.4.6" typedoc: "npm:~0.28.16" typescript: "npm:~5.9.3" @@ -5823,6 +5823,7 @@ __metadata: "@rocket.chat/icons": "workspace:~" "@rocket.chat/layout": "workspace:~" "@rocket.chat/logo": "workspace:~" + "@rocket.chat/storybook-dark-mode": "workspace:~" "@rocket.chat/styled": "workspace:~" "@storybook/addon-a11y": "npm:~9.1.17" "@storybook/addon-docs": "npm:~9.1.17" @@ -5846,7 +5847,6 @@ __metadata: react-i18next: "npm:~13.2.2" rimraf: "npm:~6.0.1" storybook: "npm:~9.1.17" - storybook-dark-mode: "patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch" ts-jest: "npm:~29.4.6" typedoc: "npm:~0.28.16" typescript: "npm:~5.9.3" @@ -5875,6 +5875,25 @@ __metadata: languageName: unknown linkType: soft +"@rocket.chat/storybook-dark-mode@workspace:packages/storybook-dark-mode, @rocket.chat/storybook-dark-mode@workspace:~": + version: 0.0.0-use.local + resolution: "@rocket.chat/storybook-dark-mode@workspace:packages/storybook-dark-mode" + dependencies: + "@storybook/global": "npm:~5.0.0" + "@storybook/icons": "npm:~1.2.12" + "@types/react": "npm:~18.3.17" + eslint: "npm:~9.39.2" + fast-deep-equal: "npm:~3.1.3" + lint-all: "workspace:~" + prettier: "npm:~3.6.2" + rimraf: "npm:~6.0.1" + typescript: "npm:~5.9.3" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + languageName: unknown + linkType: soft + "@rocket.chat/string-helpers@workspace:packages/string-helpers": version: 0.0.0-use.local resolution: "@rocket.chat/string-helpers@workspace:packages/string-helpers" @@ -6363,24 +6382,6 @@ __metadata: languageName: node linkType: hard -"@storybook/components@npm:^8.0.0": - version: 8.6.9 - resolution: "@storybook/components@npm:8.6.9" - peerDependencies: - storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/967acc44bdfdaf74087d00a5ace990402c103fadcdff3315462775ea5d8f626cb2825455e2611d97f6c92c9814a6c9fe25589b72e7238bf72ec70369897b4f9d - languageName: node - linkType: hard - -"@storybook/core-events@npm:^8.0.0": - version: 8.2.7 - resolution: "@storybook/core-events@npm:8.2.7" - peerDependencies: - storybook: ^8.2.7 - checksum: 10/88e4c0ad4b71b51e7f5eb35c2851be3cb4eadb1eb7b34f8931e4395d99d32d04caea439bb0619780378ef392851a5144d6c022900f9ebe1980037b2851c5869a - languageName: node - linkType: hard - "@storybook/core-webpack@npm:9.1.17": version: 9.1.17 resolution: "@storybook/core-webpack@npm:9.1.17" @@ -6403,23 +6404,13 @@ __metadata: languageName: node linkType: hard -"@storybook/global@npm:^5.0.0": +"@storybook/global@npm:^5.0.0, @storybook/global@npm:~5.0.0": version: 5.0.0 resolution: "@storybook/global@npm:5.0.0" checksum: 10/0e7b495f4fe7f36447e793926f1c0460ec07fd66f0da68e3150da5878f6043c9eeb9b41614a45c5ec0d48d5d383c59ca8f88b6dc7882a2a784ac9b20375d8edb languageName: node linkType: hard -"@storybook/icons@npm:^1.2.5": - version: 1.2.12 - resolution: "@storybook/icons@npm:1.2.12" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10/5df56f0856764ed7e4bb24ef7a08a8a9c93f8eedcb16dac062f1dfd3bd1fe6cb4a0aa5a0794083d95e31c04960d126a4d2028cfb4c53681bf05513bb38eae9d2 - languageName: node - linkType: hard - "@storybook/icons@npm:^1.4.0": version: 1.6.0 resolution: "@storybook/icons@npm:1.6.0" @@ -6430,12 +6421,13 @@ __metadata: languageName: node linkType: hard -"@storybook/manager-api@npm:^8.0.0": - version: 8.6.9 - resolution: "@storybook/manager-api@npm:8.6.9" +"@storybook/icons@npm:~1.2.12": + version: 1.2.12 + resolution: "@storybook/icons@npm:1.2.12" peerDependencies: - storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/84df8f304d409fcb31117e64c1fe8f4378c57a798577f9557c696276bb01effa52fc591c92e2ba5570c0036775c1532e3934d4b6ceb9ec5b09d591f8b9f6393a + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 10/5df56f0856764ed7e4bb24ef7a08a8a9c93f8eedcb16dac062f1dfd3bd1fe6cb4a0aa5a0794083d95e31c04960d126a4d2028cfb4c53681bf05513bb38eae9d2 languageName: node linkType: hard @@ -6530,15 +6522,6 @@ __metadata: languageName: node linkType: hard -"@storybook/theming@npm:^8.0.0": - version: 8.6.9 - resolution: "@storybook/theming@npm:8.6.9" - peerDependencies: - storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/24a05874713a80a1010f961725d6fc6ab0f56e1c49cf3cefdc0ac92c8b7a68455a9706a8b5a6ed2f907764fbec21d2008647f082db82eac595b76007f76c9f4f - languageName: node - linkType: hard - "@storybook/types@npm:~8.6.15": version: 8.6.15 resolution: "@storybook/types@npm:8.6.15" @@ -7087,7 +7070,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:~18.3.27": +"@types/react@npm:~18.3.17, @types/react@npm:~18.3.27": version: 18.3.27 resolution: "@types/react@npm:18.3.27" dependencies: @@ -11130,7 +11113,7 @@ __metadata: languageName: node linkType: hard -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3, fast-deep-equal@npm:~3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" checksum: 10/e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d @@ -14049,13 +14032,6 @@ __metadata: languageName: node linkType: hard -"map-or-similar@npm:^1.5.0": - version: 1.5.0 - resolution: "map-or-similar@npm:1.5.0" - checksum: 10/3cf43bcd0e7af41d7bade5f8b5be6bb9d021cc47e6008ad545d071cf3a709ba782884002f9eec6ccd51f572fc17841e07bf74628e0bc3694c33f4622b03e4b4c - languageName: node - linkType: hard - "markdown-it@npm:^14.1.0": version: 14.1.0 resolution: "markdown-it@npm:14.1.0" @@ -14251,15 +14227,6 @@ __metadata: languageName: node linkType: hard -"memoizerific@npm:^1.11.3": - version: 1.11.3 - resolution: "memoizerific@npm:1.11.3" - dependencies: - map-or-similar: "npm:^1.5.0" - checksum: 10/72b6b80699777d000f03db6e15fdabcd4afe77feb45be51fe195cb230c64a368fcfcfbb976375eac3283bd8193d6b1a67ac3081cae07f64fca73f1aa568d59e3 - languageName: node - linkType: hard - "memorystream@npm:^0.3.1": version: 0.3.1 resolution: "memorystream@npm:0.3.1" @@ -17959,38 +17926,6 @@ __metadata: languageName: node linkType: hard -"storybook-dark-mode@npm:4.0.2": - version: 4.0.2 - resolution: "storybook-dark-mode@npm:4.0.2" - dependencies: - "@storybook/components": "npm:^8.0.0" - "@storybook/core-events": "npm:^8.0.0" - "@storybook/global": "npm:^5.0.0" - "@storybook/icons": "npm:^1.2.5" - "@storybook/manager-api": "npm:^8.0.0" - "@storybook/theming": "npm:^8.0.0" - fast-deep-equal: "npm:^3.1.3" - memoizerific: "npm:^1.11.3" - checksum: 10/c9ef7bc6734df7486ff763c9da3c69505269eaf5fd7b5b489553f023b363ea892862241e6d701ad647ca5d1e64fd9a2646b8985c7ea8ac97a3bca87891db6fe5 - languageName: node - linkType: hard - -"storybook-dark-mode@patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch": - version: 4.0.2 - resolution: "storybook-dark-mode@patch:storybook-dark-mode@npm%3A4.0.2#~/.yarn/patches/storybook-dark-mode-npm-4.0.2-1acb0927fb.patch::version=4.0.2&hash=cc5078" - dependencies: - "@storybook/components": "npm:^8.0.0" - "@storybook/core-events": "npm:^8.0.0" - "@storybook/global": "npm:^5.0.0" - "@storybook/icons": "npm:^1.2.5" - "@storybook/manager-api": "npm:^8.0.0" - "@storybook/theming": "npm:^8.0.0" - fast-deep-equal: "npm:^3.1.3" - memoizerific: "npm:^1.11.3" - checksum: 10/5b799b2d421cdbae783afa34787dac0c69ab5da139d560175a11b981d8946f0584170ca42e86d96626923db8c85a19a9b71855c0ea401c6d4dbf246410bacb18 - languageName: node - linkType: hard - "storybook@npm:~9.1.17": version: 9.1.17 resolution: "storybook@npm:9.1.17"