diff --git a/packages/react-devtools-extensions/utils.js b/packages/react-devtools-extensions/utils.js index a4846f8b0e..1babd93f56 100644 --- a/packages/react-devtools-extensions/utils.js +++ b/packages/react-devtools-extensions/utils.js @@ -1,3 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + const {execSync} = require('child_process'); const {readFileSync} = require('fs'); const {resolve} = require('path'); diff --git a/packages/react-devtools-scheduling-profiler/buildUtils.js b/packages/react-devtools-scheduling-profiler/buildUtils.js new file mode 100644 index 0000000000..b0971c4861 --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/buildUtils.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +const {execSync} = require('child_process'); +const {readFileSync} = require('fs'); +const {resolve} = require('path'); + +function getGitCommit() { + try { + return execSync('git show -s --format=%h') + .toString() + .trim(); + } catch (error) { + // Mozilla runs this command from a git archive. + // In that context, there is no Git revision. + return null; + } +} + +function getVersionString() { + const packageVersion = JSON.parse( + readFileSync(resolve(__dirname, './package.json')), + ).version; + + const commit = getGitCommit(); + + return `${packageVersion}-${commit}`; +} + +module.exports = { + getVersionString, +}; diff --git a/packages/react-devtools-scheduling-profiler/package.json b/packages/react-devtools-scheduling-profiler/package.json index 60564834cd..5aa14a59f0 100644 --- a/packages/react-devtools-scheduling-profiler/package.json +++ b/packages/react-devtools-scheduling-profiler/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "react-devtools-scheduling-profiler", - "version": "0.0.1", + "version": "0.0.0", "license": "MIT", "scripts": { "build": "cross-env NODE_ENV=production cross-env TARGET=remote webpack --config webpack.config.js", @@ -18,6 +18,8 @@ }, "devDependencies": { "@pmmmwh/react-refresh-webpack-plugin": "^0.4.1", + "@reach/menu-button": "^0.11.2", + "@reach/tooltip": "^0.11.2", "babel-loader": "^8.1.0", "css-loader": "^4.2.1", "file-loader": "^6.0.0", diff --git a/packages/react-devtools-scheduling-profiler/src/App.css b/packages/react-devtools-scheduling-profiler/src/App.css new file mode 100644 index 0000000000..1ea3d75fcc --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/App.css @@ -0,0 +1,19 @@ +.DevTools { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background-color: var(--color-background); + color: var(--color-text); +} + +.TabContent { + flex: 1 1 100%; + overflow: auto; + -webkit-app-region: no-drag; +} + +.DevTools, .DevTools * { + box-sizing: border-box; + -webkit-font-smoothing: var(--font-smoothing); +} diff --git a/packages/react-devtools-scheduling-profiler/src/App.js b/packages/react-devtools-scheduling-profiler/src/App.js index 93f66ac09b..83d9238851 100644 --- a/packages/react-devtools-scheduling-profiler/src/App.js +++ b/packages/react-devtools-scheduling-profiler/src/App.js @@ -7,22 +7,30 @@ * @flow */ -import type {ReactProfilerData} from './types'; +// Reach styles need to come before any component styles. +// This makes overriding the styles simpler. +import '@reach/menu-button/styles.css'; +import '@reach/tooltip/styles.css'; import * as React from 'react'; -import {useState} from 'react'; -import ImportPage from './ImportPage'; -import CanvasPage from './CanvasPage'; +import {ModalDialogContextController} from 'react-devtools-shared/src/devtools/views/ModalDialog'; +import {SchedulingProfiler} from './SchedulingProfiler'; +import {useBrowserTheme} from './hooks'; + +import styles from './App.css'; +import 'react-devtools-shared/src/devtools/views/root.css'; export default function App() { - const [profilerData, setProfilerData] = useState( - null, - ); + useBrowserTheme(); - if (profilerData) { - return ; - } else { - return ; - } + return ( + +
+
+ +
+
+
+ ); } diff --git a/packages/react-devtools-scheduling-profiler/src/CanvasPage.js b/packages/react-devtools-scheduling-profiler/src/CanvasPage.js index f8cb3edb65..9b20cd2fb8 100644 --- a/packages/react-devtools-scheduling-profiler/src/CanvasPage.js +++ b/packages/react-devtools-scheduling-profiler/src/CanvasPage.js @@ -52,18 +52,15 @@ import { import {COLORS} from './content-views/constants'; import EventTooltip from './EventTooltip'; -import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; +import ContextMenu from './context/ContextMenu'; +import ContextMenuItem from './context/ContextMenuItem'; +import useContextMenu from './context/useContextMenu'; import {getBatchRange} from './utils/getBatchRange'; import styles from './CanvasPage.css'; const CONTEXT_MENU_ID = 'canvas'; -type ContextMenuContextData = {| - data: ReactProfilerData, - hoveredEvent: ReactHoverContextInfo | null, -|}; - type Props = {| profilerData: ReactProfilerData, |}; @@ -284,7 +281,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { useCanvasInteraction(canvasRef, interactor); - useContextMenu({ + useContextMenu({ data: { data, hoveredEvent, @@ -357,7 +354,10 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { } }); } - }, [hoveredEvent]); + }, [ + hoveredEvent, + data, // Attach onHover callbacks when views are re-created on data change + ]); useLayoutEffect(() => { const {current: userTimingMarksView} = userTimingMarksViewRef; @@ -396,7 +396,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { - {(contextData: ContextMenuContextData) => { + {contextData => { if (contextData.hoveredEvent == null) { return null; } diff --git a/packages/react-devtools-scheduling-profiler/src/ImportButton.css b/packages/react-devtools-scheduling-profiler/src/ImportButton.css new file mode 100644 index 0000000000..f0cb09ef4d --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/ImportButton.css @@ -0,0 +1,17 @@ +/** + * https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications + */ +.Input { + position: absolute !important; + height: 1px; + width: 1px; + overflow: hidden; + clip: rect(1px, 1px, 1px, 1px); +} + +.ErrorMessage { + margin: 0.5rem 0; + color: var(--color-dim); + font-family: var(--font-family-monospace); + font-size: var(--font-size-monospace-normal); +} diff --git a/packages/react-devtools-scheduling-profiler/src/ImportButton.js b/packages/react-devtools-scheduling-profiler/src/ImportButton.js new file mode 100644 index 0000000000..2f6ba344a0 --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/ImportButton.js @@ -0,0 +1,86 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import type {TimelineEvent} from '@elg/speedscope'; +import type {ReactProfilerData} from './types'; + +import * as React from 'react'; +import {useCallback, useContext, useRef} from 'react'; + +import Button from 'react-devtools-shared/src/devtools/views/Button'; +import ButtonIcon from 'react-devtools-shared/src/devtools/views/ButtonIcon'; +import {ModalDialogContext} from 'react-devtools-shared/src/devtools/views/ModalDialog'; + +import preprocessData from './utils/preprocessData'; +import {readInputData} from './utils/readInputData'; + +import styles from './ImportButton.css'; + +type Props = {| + onDataImported: (profilerData: ReactProfilerData) => void, +|}; + +export default function ImportButton({onDataImported}: Props) { + const inputRef = useRef(null); + const {dispatch: modalDialogDispatch} = useContext(ModalDialogContext); + + const handleFiles = useCallback(async () => { + const input = inputRef.current; + if (input === null) { + return; + } + + if (input.files.length > 0) { + try { + const readFile = await readInputData(input.files[0]); + const events: TimelineEvent[] = JSON.parse(readFile); + if (events.length > 0) { + onDataImported(preprocessData(events)); + } + } catch (error) { + modalDialogDispatch({ + type: 'SHOW', + title: 'Import failed', + content: ( + <> +
The profiling data you selected cannot be imported.
+ {error !== null && ( +
{error.message}
+ )} + + ), + }); + } + } + + // Reset input element to allow the same file to be re-imported + input.value = ''; + }, [onDataImported, modalDialogDispatch]); + + const uploadData = useCallback(() => { + if (inputRef.current !== null) { + inputRef.current.click(); + } + }, []); + + return ( + <> + + + + ); +} diff --git a/packages/react-devtools-scheduling-profiler/src/ImportPage.css b/packages/react-devtools-scheduling-profiler/src/ImportPage.css deleted file mode 100644 index 468f85c3f3..0000000000 --- a/packages/react-devtools-scheduling-profiler/src/ImportPage.css +++ /dev/null @@ -1,163 +0,0 @@ -.App { - min-height: 100vh; - background-color: #282c34; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.25rem; - padding: 2rem; -} - -.Card { - display: flex; - flex: 0 1 1000px; - flex-wrap: wrap; - align-items: center; - justify-content: center; -} - -.Card { - background-color: white; - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); - border-radius: 5px; - transition: 0.3s; -} - -.Card:hover { - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); -} - -.Row { - display: flex; - flex-direction: row; - flex-wrap: wrap; -} - -.Column { - margin: 2rem; - margin-right: 0; - display: flex; - flex-direction: column; - flex-basis: 100%; - flex: 1; -} -.Column:last-of-type { - margin-right: 2rem; -} - -.Link { - color: #2683E2; - transition: 0.2s; -} -.Link:hover { - color: #1572D1; -} - -kbd { - display: inline-block; - padding: 0 0.5em; - border: 1px solid #d7dfe4; - margin: 0 0.2em; - background-color: #f6f6f6; - border-radius: 0.2em; -} - -.Screenshot { - width: 35rem; - max-width: 100%; - min-width: 25rem; - align-self: center; - justify-content: center; - border: 1px solid #d7dfe4; - border-radius: 0.4em; - box-shadow: 0 2px 4px #ddd; -} - -.Header { - margin-top: 0px; -} - -.LegendKey { - margin: 0; - margin-bottom: 1.25rem; - list-style: none; - padding: 0; -} - -.LegendItem { - display: flex; - align-items: center; -} - -@keyframes spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -.Buttons { - float: left; /* Float the buttons side by side */ -} - -.ImportButton, -.ViewSourceButton { - width: 10rem; - font-size: 1.5rem; - padding: 1.5rem; - text-align: center; - transition: all 0.3s; - cursor: pointer; -} - -.ImportButton { - background-color: #2683E2; - border: none; - color: #ffffff; -} - -.ImportButton:hover { - background-color: #1572D1; -} - -.ImportButtonFile { - display: none; -} - -.ViewSourceButton { - background-color: transparent; - color: black; - border: none; -} - -.ViewSourceButton span { - cursor: pointer; - display: inline-block; - position: relative; - transition: 0.3s; -} - -.ViewSourceButton span:after { - content: '\00bb'; - position: absolute; - opacity: 0; - top: 0; - right: -20px; - transition: 0.3s; -} - -.ViewSourceButton:hover { - background-color: white; - color: black; -} - -.ViewSourceButton:hover span { - padding-right: 25px; -} - -.ViewSourceButton:hover span:after { - opacity: 1; - right: 0; -} diff --git a/packages/react-devtools-scheduling-profiler/src/ImportPage.js b/packages/react-devtools-scheduling-profiler/src/ImportPage.js deleted file mode 100644 index b6a6368989..0000000000 --- a/packages/react-devtools-scheduling-profiler/src/ImportPage.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {TimelineEvent} from '@elg/speedscope'; -import type {ReactProfilerData} from './types'; - -import * as React from 'react'; -import {useCallback, useRef} from 'react'; - -import profilerBrowser from './assets/profilerBrowser.png'; -import style from './ImportPage.css'; - -import preprocessData from './utils/preprocessData'; -import {readInputData} from './utils/readInputData'; - -type Props = {| - onDataImported: (profilerData: ReactProfilerData) => void, -|}; - -export default function ImportPage({onDataImported}: Props) { - const processTimeline = useCallback( - (events: TimelineEvent[]) => { - if (events.length > 0) { - onDataImported(preprocessData(events)); - } - }, - [onDataImported], - ); - - const handleProfilerInput = useCallback( - async (event: SyntheticInputEvent) => { - const readFile = await readInputData(event.target.files[0]); - processTimeline(JSON.parse(readFile)); - }, - [processTimeline], - ); - - const upload = useRef(null); - - return ( -
-
-
-
- logo -
-
-

React Concurrent Mode Profiler

-

- Import a captured{' '} - - performance profile - {' '} - from Chrome Devtools. To zoom, scroll while holding down{' '} - Ctrl or Shift -

-
    -
  • - - - - State Update Scheduled -
  • -
  • - - - - State Update Scheduled -
  • -
  • - - - - Suspended -
  • -
- -
- - - - -
-
-
-
-
- ); -} diff --git a/packages/react-devtools-scheduling-profiler/src/SchedulingProfiler.css b/packages/react-devtools-scheduling-profiler/src/SchedulingProfiler.css new file mode 100644 index 0000000000..b734a25e1e --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/SchedulingProfiler.css @@ -0,0 +1,101 @@ +.SchedulingProfiler { + width: 100%; + height: 100%; + position: relative; + display: flex; + flex-direction: column; + font-family: var(--font-family-sans); + font-size: var(--font-size-sans-normal); + background-color: var(--color-background); + color: var(--color-text); +} + +.SchedulingProfiler, .SchedulingProfiler * { + box-sizing: border-box; + -webkit-font-smoothing: var(--font-smoothing); +} + +.Content { + position: relative; + flex: 1 1 auto; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.Paragraph { + text-align: center; +} + +.Row { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + flex-flow: wrap; +} + +.EmptyStateContainer { + text-align: center; +} + +.Header { + font-size: var(--font-size-sans-large); + margin-bottom: 0.5rem; +} + +.Toolbar { + height: 2.25rem; + padding: 0 0.25rem; + flex: 0 0 auto; + display: flex; + align-items: center; + border-bottom: 1px solid var(--color-border); +} + +.VRule { + height: 20px; + width: 1px; + border-left: 1px solid var(--color-border); + padding-left: 0.25rem; + margin-left: 0.25rem; +} + +.Spacer { + flex: 1; +} + +.Link { + color: var(--color-button); +} + +.ScreenshotWrapper { + max-width: 30rem; + padding: 0 1rem; + margin-bottom: 2rem; +} + +.Screenshot { + width: 100%; + border-radius: 0.4em; + border: 2px solid var(--color-border); +} + +.AppName { + font-size: var(--font-size-sans-large); + margin-right: 0.5rem; + user-select: none; +} + +@media screen and (max-width: 350px) { + .AppName { + display: none; + } +} + +@media screen and (max-height: 600px) { + .ScreenshotWrapper { + display: none; + } +} \ No newline at end of file diff --git a/packages/react-devtools-scheduling-profiler/src/SchedulingProfiler.js b/packages/react-devtools-scheduling-profiler/src/SchedulingProfiler.js new file mode 100644 index 0000000000..19079a4990 --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/SchedulingProfiler.js @@ -0,0 +1,72 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import type {ReactProfilerData} from './types'; + +import * as React from 'react'; +import {useState} from 'react'; + +import ImportButton from './ImportButton'; +import {ModalDialog} from 'react-devtools-shared/src/devtools/views/ModalDialog'; +import ReactLogo from 'react-devtools-shared/src/devtools/views/ReactLogo'; + +import CanvasPage from './CanvasPage'; + +import profilerBrowser from './assets/profilerBrowser.png'; +import styles from './SchedulingProfiler.css'; + +export function SchedulingProfiler(_: {||}) { + const [profilerData, setProfilerData] = useState( + null, + ); + + const view = profilerData ? ( + + ) : ( + + ); + + return ( +
+
+ + Concurrent Mode Profiler +
+ +
+
+
+ {view} + +
+
+ ); +} + +type WelcomeProps = {| + onDataImported: (profilerData: ReactProfilerData) => void, +|}; + +const Welcome = ({onDataImported}: WelcomeProps) => ( +
+
+ Profiler screenshot +
+
Welcome!
+
+ Click the import button + to import a Chrome + performance profile. +
+
+); diff --git a/packages/react-devtools-scheduling-profiler/src/SchedulingProfilerFeatureFlags.js b/packages/react-devtools-scheduling-profiler/src/SchedulingProfilerFeatureFlags.js new file mode 100644 index 0000000000..7558576c31 --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/SchedulingProfilerFeatureFlags.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export const enableDarkMode = false; diff --git a/packages/react-devtools-scheduling-profiler/src/constants.js b/packages/react-devtools-scheduling-profiler/src/constants.js index 77f8964e82..2e463ae632 100644 --- a/packages/react-devtools-scheduling-profiler/src/constants.js +++ b/packages/react-devtools-scheduling-profiler/src/constants.js @@ -6,6 +6,10 @@ * * @flow */ -// App constants + +export { + COMFORTABLE_LINE_HEIGHT, + COMPACT_LINE_HEIGHT, +} from 'react-devtools-shared/src/constants.js'; export const REACT_TOTAL_NUM_LANES = 31; diff --git a/packages/react-devtools-scheduling-profiler/src/hooks.js b/packages/react-devtools-scheduling-profiler/src/hooks.js new file mode 100644 index 0000000000..13bd7508a2 --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/hooks.js @@ -0,0 +1,59 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import { + unstable_createMutableSource as createMutableSource, + unstable_useMutableSource as useMutableSource, + useLayoutEffect, +} from 'react'; + +import {updateThemeVariables} from 'react-devtools-shared/src/devtools/views/Settings/SettingsContext'; +import {enableDarkMode} from './SchedulingProfilerFeatureFlags'; + +export type BrowserTheme = 'dark' | 'light'; + +const DARK_MODE_QUERY = '(prefers-color-scheme: dark)'; + +const getSnapshot = window => + window.matchMedia(DARK_MODE_QUERY).matches ? 'dark' : 'light'; + +const darkModeMutableSource = createMutableSource( + window, + () => window.matchMedia(DARK_MODE_QUERY).matches, +); + +const subscribe = (window, callback) => { + const mediaQueryList = window.matchMedia(DARK_MODE_QUERY); + mediaQueryList.addEventListener('change', callback); + return () => { + mediaQueryList.removeEventListener('change', callback); + }; +}; + +export function useBrowserTheme(): void { + const theme = useMutableSource(darkModeMutableSource, getSnapshot, subscribe); + + useLayoutEffect(() => { + const documentElements = [((document.documentElement: any): HTMLElement)]; + if (enableDarkMode) { + switch (theme) { + case 'light': + updateThemeVariables('light', documentElements); + break; + case 'dark': + updateThemeVariables('dark', documentElements); + break; + default: + throw Error(`Unsupported theme value "${theme}"`); + } + } else { + updateThemeVariables('light', documentElements); + } + }, [theme]); +} diff --git a/packages/react-devtools-scheduling-profiler/src/index.css b/packages/react-devtools-scheduling-profiler/src/index.css index ec2585e8c0..0e798eef50 100644 --- a/packages/react-devtools-scheduling-profiler/src/index.css +++ b/packages/react-devtools-scheduling-profiler/src/index.css @@ -1,13 +1,21 @@ +html { + height: 100%; +} + body { + height: 100%; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + font-family: var(--font-family-sans); + font-size: var(--font-size-sans-normal); + background-color: var(--color-background); + color: var(--color-text); } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +.Container { + height: 100%; +} \ No newline at end of file diff --git a/packages/react-devtools-scheduling-profiler/src/index.js b/packages/react-devtools-scheduling-profiler/src/index.js index ffb1a8d501..d93bbb2a62 100644 --- a/packages/react-devtools-scheduling-profiler/src/index.js +++ b/packages/react-devtools-scheduling-profiler/src/index.js @@ -15,9 +15,10 @@ import {unstable_createRoot as createRoot} from 'react-dom'; import nullthrows from 'nullthrows'; import App from './App'; -import './index.css'; +import styles from './index.css'; const container = document.createElement('div'); +container.className = styles.Container; container.id = 'root'; const body = nullthrows(document.body, 'Expect document.body to exist'); diff --git a/packages/react-devtools-scheduling-profiler/webpack.config.js b/packages/react-devtools-scheduling-profiler/webpack.config.js index 20def602b2..60d6e4467f 100644 --- a/packages/react-devtools-scheduling-profiler/webpack.config.js +++ b/packages/react-devtools-scheduling-profiler/webpack.config.js @@ -4,6 +4,7 @@ const {resolve} = require('path'); const {DefinePlugin} = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); +const {getVersionString} = require('./buildUtils'); const NODE_ENV = process.env.NODE_ENV; if (!NODE_ENV) { @@ -21,6 +22,8 @@ const shouldUseDevServer = TARGET === 'local'; const builtModulesDir = resolve(__dirname, '..', '..', 'build', 'node_modules'); +const DEVTOOLS_VERSION = getVersionString(); + const imageInlineSizeLimit = 10000; const config = { @@ -41,6 +44,7 @@ const config = { __DEV__, __PROFILE__: false, __EXPERIMENTAL__: true, + 'process.env.DEVTOOLS_VERSION': `"${DEVTOOLS_VERSION}"`, }), new HtmlWebpackPlugin({ title: 'React Concurrent Mode Profiler', diff --git a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js index 9196a4b333..d13fc31b57 100644 --- a/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js +++ b/packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js @@ -248,7 +248,7 @@ function updateDisplayDensity( root.style.fontSize = fontSize; } -function updateThemeVariables( +export function updateThemeVariables( theme: Theme, documentElements: DocumentElements, ): void { diff --git a/yarn.lock b/yarn.lock index 6d31511a84..1916f50052 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1833,6 +1833,14 @@ schema-utils "^2.6.5" source-map "^0.7.3" +"@reach/auto-id@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.11.2.tgz#c66a905c5401d1ac3da8d26165b8d27d6e778fa6" + integrity sha512-YZ21b0Kb88wJ0t7QjSznWOYskARQMnmXY9Y2XZ5RyYcZ2krT4s3+ghghpfaPs6BKcrZDonZCrU65OFDJPa1jAw== + dependencies: + "@reach/utils" "0.11.2" + tslib "^2.0.0" + "@reach/auto-id@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.2.0.tgz#97f9e48fe736aa5c6f4f32cf73c1f19d005f8550" @@ -1843,6 +1851,14 @@ resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5" integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg== +"@reach/descendants@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.11.2.tgz#49ea1b5eb91aba8ae6dce57f6575c38aff1f9756" + integrity sha512-63Wdx32/RyjGRJc4UZKK7F1sIrb6jeGkDwvQH0hv0lRAhEjsiSQ1t2JTYDml3testFP48J0B2xS7JzNeY0zoQw== + dependencies: + "@reach/utils" "0.11.2" + tslib "^2.0.0" + "@reach/menu-button@^0.1.17": version "0.1.18" resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.1.18.tgz#cb9e3bf1c2a2bdb5d618697b87ad353dfbca123e" @@ -1855,11 +1871,47 @@ "@reach/window-size" "^0.1.4" warning "^4.0.2" +"@reach/menu-button@^0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.11.2.tgz#7c1a955431b6b5c25e77eeaceac347bfc728bee9" + integrity sha512-8fU8Gp7wBBhMBFSGxuF62HSdjgaib+NXEM+MhOIYcAacDnP8cxkpvag/Nm/7cMdV/O5JRuuZBralG854AxaO2g== + dependencies: + "@reach/auto-id" "0.11.2" + "@reach/descendants" "0.11.2" + "@reach/popover" "0.11.2" + "@reach/utils" "0.11.2" + prop-types "^15.7.2" + tslib "^2.0.0" + +"@reach/observe-rect@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2" + integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ== + "@reach/observe-rect@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.0.3.tgz#2ea3dcc369ab22bd9f050a92ea319321356a61e8" integrity sha1-LqPcw2mrIr2fBQqS6jGTITVqYeg= +"@reach/popover@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.11.2.tgz#d7d14d8d74b0a376e31dd9a3223d16802360e0d3" + integrity sha512-fB5lScg7Sfu3k0c+bjX7QbnFOJ1nsCWYGvrH1M9qlQolWM6gSJcD+ANnEHIb/wF85zuxzgdxZY5bjTj0RZc6Lg== + dependencies: + "@reach/portal" "0.11.2" + "@reach/rect" "0.11.2" + "@reach/utils" "0.11.2" + tabbable "^4.0.0" + tslib "^2.0.0" + +"@reach/portal@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.11.2.tgz#19a671be9ff010a345892b81e710cb6e4d9f9762" + integrity sha512-/53A/rY5oX2Y7D5TpvsP+V5cSd+4MPY6f21mAmVn4DCVwpkCFOlJ059ZL7ixS85M0Jz48YQnnvBJUqwkxqUG/g== + dependencies: + "@reach/utils" "0.11.2" + tslib "^2.0.0" + "@reach/portal@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.2.1.tgz#07720b999e0063a9e179c14dbdc60fd991cfc9fa" @@ -1867,6 +1919,16 @@ dependencies: "@reach/component-component" "^0.1.3" +"@reach/rect@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.11.2.tgz#bc92f97f87e81d1307054fd41c40874d3fbf5491" + integrity sha512-eoUWayAADi1ITtrc+8jN9NsBTUkfpORkOs5bQb4RnR6UA/3zlxo5VPuxWgWAG0BCohZlqsxg7NpvckNAyaiAAQ== + dependencies: + "@reach/observe-rect" "1.2.0" + "@reach/utils" "0.11.2" + prop-types "^15.7.2" + tslib "^2.0.0" + "@reach/rect@0.2.1", "@reach/rect@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.2.1.tgz#7343020174c90e2290b844d17c03fd9c78e6b601" @@ -1875,6 +1937,19 @@ "@reach/component-component" "^0.1.3" "@reach/observe-rect" "^1.0.3" +"@reach/tooltip@^0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.11.2.tgz#db5c11fa72995801baac157db46f5bb6cacd494b" + integrity sha512-aTi3aLkRZMHrNiHt84vnyTWNj84rPdGYkxAfaFpxgkaKpos3XmaOPiR+n/3YzQUoJXISuw8mZezcrDtsSpr3aA== + dependencies: + "@reach/auto-id" "0.11.2" + "@reach/portal" "0.11.2" + "@reach/rect" "0.11.2" + "@reach/utils" "0.11.2" + "@reach/visually-hidden" "0.11.1" + prop-types "^15.7.2" + tslib "^2.0.0" + "@reach/tooltip@^0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.2.2.tgz#a861ce38269b586597ab40417323b33d3d6dc927" @@ -1887,11 +1962,27 @@ "@reach/visually-hidden" "^0.1.4" prop-types "^15.7.2" +"@reach/utils@0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.11.2.tgz#be1f03650db56fd67a16d3fc70e5262cdb139cec" + integrity sha512-fBTolYj+rKTROXmf0zHO0rCWSvw7J0ALmYj5QxW4DmITMOH5uyRuWDWOfqohIGFbOtF/sum50WTB3tvx76d+Aw== + dependencies: + "@types/warning" "^3.0.0" + tslib "^2.0.0" + warning "^4.0.3" + "@reach/utils@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.2.3.tgz#820f6a6af4301b4c5065cfc04bb89e6a3d1d723f" integrity sha512-zM9rA8jDchr05giMhL95dPeYkK67cBQnIhCVrOKKqgWGsv+2GE/HZqeptvU4zqs0BvIqsThwov+YxVNVh5csTQ== +"@reach/visually-hidden@0.11.1": + version "0.11.1" + resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.11.1.tgz#3d7a5742acf18372f35b9e216680edd8073f35e3" + integrity sha512-TZZNSttor2jG6ZPGI35s/8G0FNSz49QrJIhAZbnUqHyPf3+jtNqAC0dOWW8Nuk+mApDDDVYd2KZ9P2vnzllNnQ== + dependencies: + tslib "^2.0.0" + "@reach/visually-hidden@^0.1.4": version "0.1.4" resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.1.4.tgz#0dc4ecedf523004337214187db70a46183bd945b" @@ -2067,6 +2158,11 @@ dependencies: source-map "^0.6.1" +"@types/warning@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" + integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= + "@types/webpack-sources@*": version "1.4.2" resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.2.tgz#5d3d4dea04008a779a90135ff96fb5c0c9e6292c" @@ -12695,6 +12791,11 @@ symbol-tree@^3.2.2, symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tabbable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261" + integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ== + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -13060,7 +13161,7 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -tslib@^1.10.0, tslib@^1.9.0: +tslib@^1.10.0: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== @@ -13070,6 +13171,16 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== +tslib@^1.9.0: + version "1.11.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.2.tgz#9c79d83272c9a7aaf166f73915c9667ecdde3cc9" + integrity sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg== + +tslib@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -13565,7 +13676,7 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -warning@^4.0.2: +warning@^4.0.2, warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==