diff --git a/.changeset/weak-snails-spar.md b/.changeset/weak-snails-spar.md new file mode 100644 index 0000000000..3cd930d5b0 --- /dev/null +++ b/.changeset/weak-snails-spar.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Avoiding re-running tests on cleanup. diff --git a/.changeset/weak-snails-spark.md b/.changeset/weak-snails-spark.md new file mode 100644 index 0000000000..c82626ea39 --- /dev/null +++ b/.changeset/weak-snails-spark.md @@ -0,0 +1,5 @@ +--- +'@backstage/test-utils': minor +--- + +Test App Wrapper is now using `UnifiedThemeProvider` for supporting MUI v5 next to MUI v4 in tests. diff --git a/.changeset/weak-snails-sparkl.md b/.changeset/weak-snails-sparkl.md new file mode 100644 index 0000000000..9bbc7d843b --- /dev/null +++ b/.changeset/weak-snails-sparkl.md @@ -0,0 +1,17 @@ +--- +'@backstage/app-defaults': minor +'@backstage/theme': minor +--- + +**MUI v5 Support:** Adding platform-wide support for MUI v5 allowing a transition phase for migrating central plugins & components over. We still support v4 instances & plugins by adding a + +To allow the future support of plugins & components using MUI v5 you want to upgrade your `AppTheme`'s to using the `UnifiedThemeProvider` + +```diff + Provider: ({ children }) => ( +- +- {children} +- ++ + ), +``` diff --git a/.changeset/weak-snails-sparkle.md b/.changeset/weak-snails-sparkle.md new file mode 100644 index 0000000000..95a2255e56 --- /dev/null +++ b/.changeset/weak-snails-sparkle.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Enforcing MUI v5 specific linting to minimize bundle size. diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index a5df84f8dc..61e94e9ef4 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -165,16 +165,17 @@ module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { The configuration factory also provides utilities for extending the configuration in ways that are otherwise very cumbersome to do with plain ESLint, particularly for rules like `no-restricted-syntax`. These are the extra keys that are available: -| Key | Description | -| ----------------------- | ------------------------------------------------------------------ | -| `tsRules` | Additional rules to apply to TypeScript files | -| `testRules` | Additional rules to apply to tests files | -| `restrictedImports` | Additional paths to add to `no-restricted-imports` | -| `restrictedSrcImports` | Additional paths to add to `no-restricted-imports` in src files | -| `restrictedTestImports` | Additional paths to add to `no-restricted-imports` in test files | -| `restrictedSyntax` | Additional patterns to add to `no-restricted-syntax` | -| `restrictedSrcSyntax` | Additional patterns to add to `no-restricted-syntax` in src files | -| `restrictedTestSyntax` | Additional patterns to add to `no-restricted-syntax` in test files | +| Key | Description | +| -------------------------- | ------------------------------------------------------------------ | +| `tsRules` | Additional rules to apply to TypeScript files | +| `testRules` | Additional rules to apply to tests files | +| `restrictedImports` | Additional paths to add to `no-restricted-imports` | +| `restrictedImportPatterns` | Additional patterns to add to `no-restricted-imports` | +| `restrictedSrcImports` | Additional paths to add to `no-restricted-imports` in src files | +| `restrictedTestImports` | Additional paths to add to `no-restricted-imports` in test files | +| `restrictedSyntax` | Additional patterns to add to `no-restricted-syntax` | +| `restrictedSrcSyntax` | Additional patterns to add to `no-restricted-syntax` in src files | +| `restrictedTestSyntax` | Additional patterns to add to `no-restricted-syntax` in test files | ## Type Checking diff --git a/packages/app-defaults/src/defaults/themes.tsx b/packages/app-defaults/src/defaults/themes.tsx index 397c160168..10368bd3bc 100644 --- a/packages/app-defaults/src/defaults/themes.tsx +++ b/packages/app-defaults/src/defaults/themes.tsx @@ -15,11 +15,12 @@ */ import React from 'react'; -import { darkTheme, lightTheme } from '@backstage/theme'; +import { + UnifiedThemeProvider, + themes as builtinThemes, +} from '@backstage/theme'; import DarkIcon from '@material-ui/icons/Brightness2'; import LightIcon from '@material-ui/icons/WbSunny'; -import { ThemeProvider } from '@material-ui/core/styles'; -import CssBaseline from '@material-ui/core/CssBaseline'; import { AppTheme } from '@backstage/core-plugin-api'; export const themes: AppTheme[] = [ @@ -29,9 +30,7 @@ export const themes: AppTheme[] = [ variant: 'light', icon: , Provider: ({ children }) => ( - - {children} - + ), }, { @@ -40,9 +39,7 @@ export const themes: AppTheme[] = [ variant: 'dark', icon: , Provider: ({ children }) => ( - - {children} - + ), }, ]; diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index dde853fdff..36b51324fc 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -24,6 +24,7 @@ const { join: joinPath } = require('path'); * - `tsRules`: Additional ESLint rules to apply to TypeScript * - `testRules`: Additional ESLint rules to apply to tests * - `restrictedImports`: Additional paths to add to no-restricted-imports + * - `restrictedImportsPattern`: Additional patterns to add to no-restricted-imports * - `restrictedSrcImports`: Additional paths to add to no-restricted-imports in src files * - `restrictedTestImports`: Additional paths to add to no-restricted-imports in test files * - `restrictedSyntax`: Additional patterns to add to no-restricted-syntax @@ -44,6 +45,7 @@ function createConfig(dir, extraConfig = {}) { testRules, restrictedImports, + restrictedImportPatterns, restrictedSrcImports, restrictedTestImports, restrictedSyntax, @@ -114,6 +116,7 @@ function createConfig(dir, extraConfig = {}) { '*.test*', '**/__testUtils__/**', '**/__mocks__/**', + ...(restrictedImportPatterns ?? []), ], }, ], @@ -208,9 +211,19 @@ function createConfigForRole(dir, role, extraConfig = {}) { name: '@material-ui/icons/', // because this is possible too ._. message: "Please import '@material-ui/icons/' instead.", }, + { + // https://mui.com/material-ui/guides/minimizing-bundle-size/ + name: '@mui/material', + message: "Please import '@mui/material/...' instead.", + }, ...require('module').builtinModules, ...(extraConfig.restrictedImports ?? []), ], + // https://mui.com/material-ui/guides/minimizing-bundle-size/ + restrictedImportPatterns: [ + '@mui/*/*/*', + ...(extraConfig.restrictedImportPatterns ?? []), + ], tsRules: { 'react/prop-types': 0, ...extraConfig.tsRules, diff --git a/packages/core-app-api/src/app/types.ts b/packages/core-app-api/src/app/types.ts index 3d9005b0c0..c34407ca3a 100644 --- a/packages/core-app-api/src/app/types.ts +++ b/packages/core-app-api/src/app/types.ts @@ -236,21 +236,13 @@ export type AppOptions = { * title: 'Light Theme', * variant: 'light', * icon: , - * Provider: ({ children }) => ( - * - * {children} - * - * ), + * Provider: ({ children }) => , * }, { * id: 'dark', * title: 'Dark Theme', * variant: 'dark', * icon: , - * Provider: ({ children }) => ( - * - * {children} - * - * ), + * Provider: ({ children }) => , * }] * ``` */ diff --git a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx index 0159d8f503..8fdace3766 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx @@ -89,7 +89,11 @@ export function OAuthRequestDialog(_props: {}) { classes={{ root: classes.title }} id="oauth-req-dialog-title" > - + Login Required {authRedirect ? ( diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 8b644ad2d1..6545cc312a 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -17,9 +17,7 @@ import React, { ComponentType, ReactNode, ReactElement } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { Route } from 'react-router-dom'; -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core/styles'; -import { CssBaseline } from '@material-ui/core'; +import { UnifiedThemeProvider, themes } from '@backstage/theme'; import MockIcon from '@material-ui/icons/AcUnit'; import { createSpecializedApp } from '@backstage/core-app-api'; import { @@ -142,9 +140,9 @@ export function createTestAppWrapper( title: 'Test App Theme', variant: 'light', Provider: ({ children }) => ( - - {children} - + + {children} + ), }, ], diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 863ab81b68..fe05ca6b4e 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -3,13 +3,19 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import type { ComponentsProps } from '@material-ui/core/styles/props'; import { Overrides } from '@material-ui/core/styles/overrides'; -import { Palette } from '@material-ui/core/styles/createPalette'; -import { PaletteOptions } from '@material-ui/core/styles/createPalette'; -import { Theme } from '@material-ui/core'; -import { ThemeOptions } from '@material-ui/core'; +import type { Palette } from '@material-ui/core/styles/createPalette'; +import type { PaletteOptions } from '@material-ui/core/styles/createPalette'; +import { PaletteOptions as PaletteOptions_2 } from '@mui/material/styles'; +import { ReactNode } from 'react'; +import { Theme } from '@mui/material/styles'; +import { Theme as Theme_2 } from '@material-ui/core'; +import { ThemeOptions } from '@mui/material/styles'; +import { ThemeOptions as ThemeOptions_2 } from '@material-ui/core/styles'; +import type { ThemeOptions as ThemeOptions_3 } from '@material-ui/core'; -// @public +// @public @deprecated export type BackstagePalette = Palette & BackstagePaletteAdditions; // @public @@ -75,12 +81,12 @@ export type BackstagePaletteAdditions = { }; }; -// @public +// @public @deprecated export type BackstagePaletteOptions = PaletteOptions & BackstagePaletteAdditions; -// @public -export interface BackstageTheme extends Theme { +// @public @deprecated +export interface BackstageTheme extends Theme_2 { // (undocumented) getPageTheme: (selector: PageThemeSelector) => PageTheme; // (undocumented) @@ -90,7 +96,13 @@ export interface BackstageTheme extends Theme { } // @public -export interface BackstageThemeOptions extends ThemeOptions { +export type BackstageThemeAdditions = { + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +}; + +// @public @deprecated +export interface BackstageThemeOptions extends ThemeOptions_3 { // (undocumented) getPageTheme: (selector: PageThemeSelector) => PageTheme; // (undocumented) @@ -99,22 +111,86 @@ export interface BackstageThemeOptions extends ThemeOptions { palette: BackstagePaletteOptions; } +// @public +export interface BaseThemeOptionsInput { + // (undocumented) + defaultPageTheme?: string; + // (undocumented) + fontFamily?: string; + // (undocumented) + htmlFontSize?: number; + // (undocumented) + pageTheme?: Record; + // (undocumented) + palette: PaletteOptions; +} + // @public export const colorVariants: Record; // @public -export function createTheme(options: SimpleThemeOptions): BackstageTheme; +export function createBaseThemeOptions( + options: BaseThemeOptionsInput, +): { + palette: PaletteOptions; + typography: { + htmlFontSize: number; + fontFamily: string; + h1: { + fontSize: number; + fontWeight: number; + marginBottom: number; + }; + h2: { + fontSize: number; + fontWeight: number; + marginBottom: number; + }; + h3: { + fontSize: number; + fontWeight: number; + marginBottom: number; + }; + h4: { + fontWeight: number; + fontSize: number; + marginBottom: number; + }; + h5: { + fontWeight: number; + fontSize: number; + marginBottom: number; + }; + h6: { + fontWeight: number; + fontSize: number; + marginBottom: number; + }; + }; + page: PageTheme; + getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; +}; + +// @public @deprecated +export function createTheme(options: SimpleThemeOptions): Theme_2; + +// @public @deprecated +export function createThemeOptions(options: SimpleThemeOptions): ThemeOptions_3; + +// @public @deprecated +export function createThemeOverrides(theme: Theme_2): Overrides; // @public -export function createThemeOptions( - options: SimpleThemeOptions, -): BackstageThemeOptions; +export function createUnifiedTheme(options: UnifiedThemeOptions): UnifiedTheme; // @public -export function createThemeOverrides(theme: BackstageTheme): Overrides; +export function createUnifiedThemeFromV4(options: ThemeOptions_2): UnifiedTheme; + +// @public @deprecated +export const darkTheme: Theme_2; // @public -export const darkTheme: BackstageTheme; +export const defaultComponentThemes: ThemeOptions['components']; // @public export function genPageTheme(props: { @@ -125,8 +201,8 @@ export function genPageTheme(props: { }; }): PageTheme; -// @public -export const lightTheme: BackstageTheme; +// @public @deprecated +export const lightTheme: Theme_2; // @public export type PageTheme = { @@ -145,14 +221,214 @@ export type PageThemeSelector = { }; // @public -export const shapes: Record; +export const palettes: { + light: { + type: 'light'; + mode: 'light'; + background: { + default: string; + paper: string; + }; + status: { + ok: string; + warning: string; + error: string; + running: string; + pending: string; + aborted: string; + }; + bursts: { + fontColor: string; + slackChannelText: string; + backgroundColor: { + default: string; + }; + gradient: { + linear: string; + }; + }; + primary: { + main: string; + }; + banner: { + info: string; + error: string; + text: string; + link: string; + closeButtonColor: string; + warning: string; + }; + border: string; + textContrast: string; + textVerySubtle: string; + textSubtle: string; + highlight: string; + errorBackground: string; + warningBackground: string; + infoBackground: string; + errorText: string; + infoText: string; + warningText: string; + linkHover: string; + link: string; + gold: string; + navigation: { + background: string; + indicator: string; + color: string; + selectedColor: string; + navItem: { + hoverBackground: string; + }; + submenu: { + background: string; + }; + }; + pinSidebarButton: { + icon: string; + background: string; + }; + tabbar: { + indicator: string; + }; + }; + dark: { + type: 'dark'; + mode: 'dark'; + background: { + default: string; + paper: string; + }; + status: { + ok: string; + warning: string; + error: string; + running: string; + pending: string; + aborted: string; + }; + bursts: { + fontColor: string; + slackChannelText: string; + backgroundColor: { + default: string; + }; + gradient: { + linear: string; + }; + }; + primary: { + main: string; + dark: string; + }; + secondary: { + main: string; + }; + banner: { + info: string; + error: string; + text: string; + link: string; + closeButtonColor: string; + warning: string; + }; + border: string; + textContrast: string; + textVerySubtle: string; + textSubtle: string; + highlight: string; + errorBackground: string; + warningBackground: string; + infoBackground: string; + errorText: string; + infoText: string; + warningText: string; + linkHover: string; + link: string; + gold: string; + navigation: { + background: string; + indicator: string; + color: string; + selectedColor: string; + navItem: { + hoverBackground: string; + }; + submenu: { + background: string; + }; + }; + pinSidebarButton: { + icon: string; + background: string; + }; + tabbar: { + indicator: string; + }; + }; +}; // @public +export const shapes: Record; + +// @public @deprecated export type SimpleThemeOptions = { - palette: BackstagePaletteOptions; - defaultPageTheme: string; + palette: PaletteOptions; + defaultPageTheme?: string; pageTheme?: Record; fontFamily?: string; htmlFontSize?: number; }; + +// @public +export const themes: { + light: UnifiedTheme; + dark: UnifiedTheme; +}; + +// @public +export function transformV5ComponentThemesToV4( + theme: Theme, + components?: ThemeOptions['components'], +): { + overrides: Overrides; + props: ComponentsProps; +}; + +// @public +export interface UnifiedTheme { + // (undocumented) + getTheme(version: string): unknown | undefined; +} + +// @public +export interface UnifiedThemeOptions { + // (undocumented) + components?: ThemeOptions['components']; + // (undocumented) + defaultPageTheme?: string; + // (undocumented) + fontFamily?: string; + // (undocumented) + htmlFontSize?: number; + // (undocumented) + pageTheme?: Record; + // (undocumented) + palette: PaletteOptions & PaletteOptions_2; +} + +// @public +export function UnifiedThemeProvider( + props: UnifiedThemeProviderProps, +): JSX.Element; + +// @public +export interface UnifiedThemeProviderProps { + // (undocumented) + children: ReactNode; + // (undocumented) + noCssBaseline?: boolean; + // (undocumented) + theme: UnifiedTheme; +} ``` diff --git a/packages/theme/package.json b/packages/theme/package.json index fbc767fb2f..52def665d6 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -32,9 +32,13 @@ "test": "backstage-cli package test" }, "dependencies": { - "@material-ui/core": "^4.12.2" + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@mui/material": "^5.12.2" }, "peerDependencies": { + "@material-ui/core": "^4.12.2", + "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0", "react-dom": "^16.13.1 || ^17.0.0" }, diff --git a/packages/theme/src/base/createBaseThemeOptions.ts b/packages/theme/src/base/createBaseThemeOptions.ts new file mode 100644 index 0000000000..e54e920deb --- /dev/null +++ b/packages/theme/src/base/createBaseThemeOptions.ts @@ -0,0 +1,98 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PageTheme, PageThemeSelector } from './types'; +import { pageTheme as defaultPageThemes } from './pageTheme'; + +const DEFAULT_HTML_FONT_SIZE = 16; +const DEFAULT_FONT_FAMILY = + '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif'; +const DEFAULT_PAGE_THEME = 'home'; + +/** + * Options for {@link createBaseThemeOptions}. + * + * @public + */ +export interface BaseThemeOptionsInput { + palette: PaletteOptions; + defaultPageTheme?: string; + pageTheme?: Record; + fontFamily?: string; + htmlFontSize?: number; +} + +/** + * A helper for creating theme options. + * + * @public + */ +export function createBaseThemeOptions( + options: BaseThemeOptionsInput, +) { + const { + palette, + htmlFontSize = DEFAULT_HTML_FONT_SIZE, + fontFamily = DEFAULT_FONT_FAMILY, + defaultPageTheme = DEFAULT_PAGE_THEME, + pageTheme = defaultPageThemes, + } = options; + + if (!pageTheme[defaultPageTheme]) { + throw new Error(`${defaultPageTheme} is not defined in pageTheme.`); + } + + return { + palette, + typography: { + htmlFontSize, + fontFamily, + h1: { + fontSize: 54, + fontWeight: 700, + marginBottom: 10, + }, + h2: { + fontSize: 40, + fontWeight: 700, + marginBottom: 8, + }, + h3: { + fontSize: 32, + fontWeight: 700, + marginBottom: 6, + }, + h4: { + fontWeight: 700, + fontSize: 28, + marginBottom: 6, + }, + h5: { + fontWeight: 700, + fontSize: 24, + marginBottom: 4, + }, + h6: { + fontWeight: 700, + fontSize: 20, + marginBottom: 2, + }, + }, + page: pageTheme[defaultPageTheme], + getPageTheme: ({ themeId }: PageThemeSelector) => + pageTheme[themeId] ?? pageTheme[defaultPageTheme], + }; +} diff --git a/packages/theme/src/base/index.ts b/packages/theme/src/base/index.ts new file mode 100644 index 0000000000..4bb80aa42b --- /dev/null +++ b/packages/theme/src/base/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { createBaseThemeOptions } from './createBaseThemeOptions'; +export type { BaseThemeOptionsInput } from './createBaseThemeOptions'; +export { colorVariants, genPageTheme, pageTheme, shapes } from './pageTheme'; +export { palettes } from './palettes'; +export type { + BackstageThemeAdditions, + BackstagePaletteAdditions, + PageTheme, + PageThemeSelector, +} from './types'; diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/base/pageTheme.ts similarity index 99% rename from packages/theme/src/pageTheme.ts rename to packages/theme/src/base/pageTheme.ts index dd36d7641b..12a73b6089 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/base/pageTheme.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { PageTheme } from './types'; /** diff --git a/packages/theme/src/themes.ts b/packages/theme/src/base/palettes.ts similarity index 87% rename from packages/theme/src/themes.ts rename to packages/theme/src/base/palettes.ts index 23438a1c14..5e70afd7b8 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/base/palettes.ts @@ -14,20 +14,18 @@ * limitations under the License. */ -import { createTheme } from './baseTheme'; -import { pageTheme } from './pageTheme'; -import { yellow } from '@material-ui/core/colors'; - /** - * The default Backstage light theme. + * Built-in Backstage color palettes. * * @public */ -export const lightTheme = createTheme({ - palette: { - type: 'light', +export const palettes = { + light: { + type: 'light' as const, + mode: 'light' as const, background: { default: '#F8F8F8', + paper: '#FFFFFF', }, status: { ok: '#1DB954', @@ -71,7 +69,7 @@ export const lightTheme = createTheme({ warningText: '#000000', linkHover: '#2196F3', link: '#0A6EBE', - gold: yellow.A700, + gold: '#FFD600', navigation: { background: '#171717', indicator: '#9BF0E1', @@ -92,20 +90,12 @@ export const lightTheme = createTheme({ indicator: '#9BF0E1', }, }, - defaultPageTheme: 'home', - pageTheme, -}); - -/** - * The default Backstage dark theme. - * - * @public - */ -export const darkTheme = createTheme({ - palette: { - type: 'dark', + dark: { + type: 'dark' as const, + mode: 'dark' as const, background: { default: '#333333', + paper: '#424242', }, status: { ok: '#71CF88', @@ -153,7 +143,7 @@ export const darkTheme = createTheme({ warningText: '#000000', linkHover: '#82BAFD', link: '#9CC9FF', - gold: yellow.A700, + gold: '#FFD600', navigation: { background: '#424242', indicator: '#9BF0E1', @@ -174,6 +164,4 @@ export const darkTheme = createTheme({ indicator: '#9BF0E1', }, }, - defaultPageTheme: 'home', - pageTheme, -}); +}; diff --git a/packages/theme/src/types.ts b/packages/theme/src/base/types.ts similarity index 63% rename from packages/theme/src/types.ts rename to packages/theme/src/base/types.ts index 0295e491f1..8f71ce4292 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/base/types.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,6 @@ * limitations under the License. */ -import { Theme, ThemeOptions } from '@material-ui/core'; -import { - PaletteOptions, - Palette, -} from '@material-ui/core/styles/createPalette'; - /** * Backstage specific additions to the material-ui palette. * @@ -90,21 +84,6 @@ export type BackstagePaletteAdditions = { }; }; -/** - * The full Backstage palette. - * - * @public - */ -export type BackstagePalette = Palette & BackstagePaletteAdditions; - -/** - * The full Backstage palette options. - * - * @public - */ -export type BackstagePaletteOptions = PaletteOptions & - BackstagePaletteAdditions; - /** * Selector for what page theme to use. * @@ -114,48 +93,6 @@ export type PageThemeSelector = { themeId: string; }; -/** - * A Backstage theme. - * - * @public - */ -export interface BackstageTheme extends Theme { - palette: BackstagePalette; - page: PageTheme; - getPageTheme: (selector: PageThemeSelector) => PageTheme; -} - -/** - * Backstage theme options. - * - * @public - * @remarks - * - * This is essentially a partial theme definition made by the user, that then - * gets merged together with defaults and other values to form the final - * {@link BackstageTheme}. - * - */ -export interface BackstageThemeOptions extends ThemeOptions { - palette: BackstagePaletteOptions; - page: PageTheme; - getPageTheme: (selector: PageThemeSelector) => PageTheme; -} - -/** - * A simpler configuration for creating a new theme that just tweaks some parts - * of the backstage one. - * - * @public - */ -export type SimpleThemeOptions = { - palette: BackstagePaletteOptions; - defaultPageTheme: string; - pageTheme?: Record; - fontFamily?: string; - htmlFontSize?: number; -}; - /** * The theme definitions for a given layout page. * @@ -167,3 +104,13 @@ export type PageTheme = { backgroundImage: string; fontColor: string; }; + +/** + * Backstage specific additions to the material-ui theme. + * + * @public + */ +export type BackstageThemeAdditions = { + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +}; diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts index 41f827bf43..b0e3590273 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ * @packageDocumentation */ -export * from './themes'; -export * from './baseTheme'; -export * from './types'; -export * from './pageTheme'; +export * from './unified'; +export * from './base'; +export * from './v4'; +export * from './v5'; diff --git a/packages/theme/src/unified/MuiClassNameSetup.ts b/packages/theme/src/unified/MuiClassNameSetup.ts new file mode 100644 index 0000000000..42b948af32 --- /dev/null +++ b/packages/theme/src/unified/MuiClassNameSetup.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className'; + +/** + * This API is introduced in @mui/material (v5.0.5) as a replacement of deprecated createGenerateClassName & only affects v5 MUI components from `@mui/*` + */ +ClassNameGenerator.configure(componentName => { + return `v5-${componentName}`; +}); diff --git a/packages/theme/src/unified/UnifiedTheme.tsx b/packages/theme/src/unified/UnifiedTheme.tsx new file mode 100644 index 0000000000..0c5f80357a --- /dev/null +++ b/packages/theme/src/unified/UnifiedTheme.tsx @@ -0,0 +1,101 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Theme as Mui4Theme, + ThemeOptions as ThemeOptionsV4, + createTheme, +} from '@material-ui/core/styles'; +import type { PaletteOptions as PaletteOptionsV4 } from '@material-ui/core/styles/createPalette'; +import { PaletteOptions as PaletteOptionsV5 } from '@mui/material/styles'; +import { + adaptV4Theme, + Theme as Mui5Theme, + createTheme as createV5Theme, + ThemeOptions as ThemeOptionsV5, +} from '@mui/material/styles'; +import { transformV5ComponentThemesToV4 } from './overrides'; +import { PageTheme } from '../base/types'; +import { defaultComponentThemes } from '../v5'; +import { createBaseThemeOptions } from '../base/createBaseThemeOptions'; +import { UnifiedTheme } from './types'; + +export class UnifiedThemeHolder implements UnifiedTheme { + #themes = new Map(); + + constructor(v4?: Mui4Theme, v5?: Mui5Theme) { + this.#themes = new Map(); + if (v4) { + this.#themes.set('v4', v4); + } + if (v5) { + this.#themes.set('v5', v5); + } + } + + getTheme(version: string): unknown | undefined { + return this.#themes.get(version); + } +} + +/** + * Options for creating a new {@link UnifiedTheme}. + * + * @public + */ +export interface UnifiedThemeOptions { + palette: PaletteOptionsV4 & PaletteOptionsV5; + defaultPageTheme?: string; + pageTheme?: Record; + fontFamily?: string; + htmlFontSize?: number; + components?: ThemeOptionsV5['components']; +} + +/** + * Creates a new {@link UnifiedTheme} using the provided options. + * + * @public + */ +export function createUnifiedTheme(options: UnifiedThemeOptions): UnifiedTheme { + const themeOptions = createBaseThemeOptions(options); + const components = { ...defaultComponentThemes, ...options.components }; + const v5Theme = createV5Theme({ ...themeOptions, components }); + + // TODO: Not super relevant in the beginning + /* const mui4Styles = maybeLoadMui4Styles(); + if (!mui4Styles) { + return new UnifiedThemeHolder(undefined, v5Theme); + } */ + + const v4Overrides = transformV5ComponentThemesToV4(v5Theme, components); + const v4Theme = { ...createTheme(themeOptions), ...v4Overrides }; + return new UnifiedThemeHolder(v4Theme, v5Theme); +} + +/** + * Creates a new {@link UnifiedTheme} using MUI v4 theme options. + * Note that this uses `adaptV4Theme` from MUI v5, which is deprecated. + * + * @public + */ +export function createUnifiedThemeFromV4( + options: ThemeOptionsV4, +): UnifiedTheme { + const v5Theme = adaptV4Theme(options as any); + const v4Theme = createTheme(options); + return new UnifiedThemeHolder(v4Theme, v5Theme); +} diff --git a/packages/theme/src/unified/UnifiedThemeProvider.tsx b/packages/theme/src/unified/UnifiedThemeProvider.tsx new file mode 100644 index 0000000000..c7054e0e55 --- /dev/null +++ b/packages/theme/src/unified/UnifiedThemeProvider.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode } from 'react'; +import './MuiClassNameSetup'; +import { ThemeProvider } from '@material-ui/core/styles'; +import { + StyledEngineProvider, + ThemeProvider as Mui5Provider, +} from '@mui/material/styles'; +import CSSBaseline from '@mui/material/CssBaseline'; +import { UnifiedTheme } from './types'; + +/** + * Props for {@link UnifiedThemeProvider}. + * + * @public + */ +export interface UnifiedThemeProviderProps { + children: ReactNode; + theme: UnifiedTheme; + noCssBaseline?: boolean; +} + +/** + * Provides themes for all MUI versions supported by the provided unified theme. + * + * @public + */ +export function UnifiedThemeProvider( + props: UnifiedThemeProviderProps, +): JSX.Element { + const { children, theme, noCssBaseline = false } = props; + + const v4Theme = theme.getTheme('v4'); + const v5Theme = theme.getTheme('v5'); + + let cssBaseline: JSX.Element | undefined = undefined; + if (!noCssBaseline) { + cssBaseline = ; + } + + let result = ( + <> + {cssBaseline} + {children} + + ); + + if (v4Theme) { + result = {result}; + } + + if (v5Theme) { + result = ( + + {result} + + ); + } + + return result; +} diff --git a/packages/theme/src/unified/index.ts b/packages/theme/src/unified/index.ts new file mode 100644 index 0000000000..f5c805d3ed --- /dev/null +++ b/packages/theme/src/unified/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { transformV5ComponentThemesToV4 } from './overrides'; +export { createUnifiedTheme, createUnifiedThemeFromV4 } from './UnifiedTheme'; +export type { UnifiedThemeOptions } from './UnifiedTheme'; +export { themes } from './themes'; +export { UnifiedThemeProvider } from './UnifiedThemeProvider'; +export type { UnifiedThemeProviderProps } from './UnifiedThemeProvider'; +export type { UnifiedTheme } from './types'; diff --git a/packages/theme/src/unified/overrides.test.ts b/packages/theme/src/unified/overrides.test.ts new file mode 100644 index 0000000000..e84cedade6 --- /dev/null +++ b/packages/theme/src/unified/overrides.test.ts @@ -0,0 +1,165 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Theme } from '@mui/material/styles'; +import { transformV5ComponentThemesToV4 } from './overrides'; + +describe('transformV5ComponentThemesToV4', () => { + const mockTheme = { + palette: { + primary: { + main: 'red', + }, + }, + } as unknown as Theme; + it('transforms empty component themes', () => { + expect(transformV5ComponentThemesToV4(mockTheme)).toEqual({ + overrides: {}, + props: {}, + }); + expect(transformV5ComponentThemesToV4(mockTheme, {})).toEqual({ + overrides: {}, + props: {}, + }); + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: undefined, + defaultProps: undefined, + }, + }), + ).toEqual({ overrides: {}, props: {} }); + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: {}, + defaultProps: {}, + }, + }), + ).toEqual({ overrides: { MuiButton: {} }, props: { MuiButton: {} } }); + }); + + it('transforms component themes', () => { + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: { + root: { + color: 'green', + }, + }, + defaultProps: { + disableRipple: true, + }, + }, + }), + ).toEqual({ + overrides: { + MuiButton: { + root: { + color: 'green', + }, + }, + }, + props: { + MuiButton: { + disableRipple: true, + }, + }, + }); + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: { + root: ({ theme }) => ({ + color: theme.palette.primary.main, + }), + }, + }, + }), + ).toEqual({ + overrides: { + MuiButton: { + root: { + color: 'red', + }, + }, + }, + props: {}, + }); + }); + + it('transforms CSSBaseline theme', () => { + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiCssBaseline: { + styleOverrides: theme => ({ + html: { + color: theme.palette.primary.main, + }, + }), + defaultProps: { + enableColorScheme: true, + }, + }, + }), + ).toEqual({ + overrides: { + MuiCssBaseline: { + '@global': { + html: { + color: 'red', + }, + }, + }, + }, + props: { + MuiCssBaseline: { + enableColorScheme: true, + }, + }, + }); + }); + + it('transform state styles', () => { + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: { + root: { + color: 'green', + '&.Mui-disabled': { + color: 'red', + }, + }, + }, + }, + }), + ).toEqual({ + overrides: { + MuiButton: { + root: { + color: 'green', + }, + disabled: { + color: 'red', + }, + }, + }, + props: {}, + }); + }); +}); diff --git a/packages/theme/src/unified/overrides.ts b/packages/theme/src/unified/overrides.ts new file mode 100644 index 0000000000..7417fccedc --- /dev/null +++ b/packages/theme/src/unified/overrides.ts @@ -0,0 +1,142 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Overrides } from '@material-ui/core/styles/overrides'; +import type { ComponentsProps } from '@material-ui/core/styles/props'; +import { ComponentsOverrides, Theme, ThemeOptions } from '@mui/material/styles'; +import { CSSProperties } from 'react'; + +type V5Override = ComponentsOverrides[Exclude< + keyof ComponentsOverrides, + 'MuiCssBaseline' +>]; +type V4Override = Overrides[keyof Overrides]; +type StaticStyleRules = Record< + string, + CSSProperties | Record +>; + +// Converts callback-based overrides to static styles, e.g. +// { root: theme => ({ color: theme.color }) } -> { root: { color: 'red' } } +function adaptV5CssBaselineOverride( + theme: Theme, + overrides: ComponentsOverrides['MuiCssBaseline'], +): StaticStyleRules | undefined { + if (!overrides || typeof overrides === 'string') { + return undefined; + } + + const styles = typeof overrides === 'function' ? overrides(theme) : overrides; + if (styles) { + return { '@global': styles } as StaticStyleRules; + } + + return undefined; +} + +// Converts callback-based overrides to static styles, e.g. +// { root: theme => ({ color: theme.color }) } -> { root: { color: 'red' } } +function adaptV5Override( + theme: Theme, + overrides: V5Override, +): StaticStyleRules | undefined { + if (!overrides || typeof overrides === 'string') { + return undefined; + } + if (typeof overrides === 'object') { + return Object.fromEntries( + Object.entries(overrides).map(([className, style]) => { + if (typeof style === 'function') { + return [className, style({ theme })]; + } + return [className, style]; + }), + ); + } + return overrides as StaticStyleRules; +} + +const stateStyleKeyPattern = /^&.Mui-([\w-]+)$/; + +// Move state style overrides to the top level, e.g. +// { root: { '&.Mui-active': { color: 'red' } } } -> { active: { color: 'red' } } +function extractV5StateOverrides( + overrides: StaticStyleRules | undefined, +): StaticStyleRules | undefined { + let output = overrides; + if (!overrides || typeof overrides !== 'object') { + return output; + } + for (const className of Object.keys(overrides)) { + const styles = overrides[className]; + if (!styles || typeof styles !== 'object') { + continue; + } + for (const _styleKey of Object.keys(styles)) { + const styleKey = _styleKey as keyof typeof styles; + const match = styleKey.match(stateStyleKeyPattern); + if (match) { + const [, state] = match; + const { [styleKey]: stateStyles, ...restStyles } = styles; + if (stateStyles) { + output = { + ...output, + [className]: restStyles, + [state]: stateStyles, + }; + } + } + } + } + return output; +} + +/** + * Transform MUI v5 component themes into a v4 theme props and overrides. + * + * @public + */ +export function transformV5ComponentThemesToV4( + theme: Theme, + components: ThemeOptions['components'] = {}, +): { overrides: Overrides; props: ComponentsProps } { + const overrides: Record = {}; + const props: Record = {}; + + for (const name of Object.keys(components)) { + const component = components[name as keyof typeof components]; + if (!component) { + continue; + } + if ('styleOverrides' in component) { + if (name === 'MuiCssBaseline') { + overrides[name] = adaptV5CssBaselineOverride( + theme, + component.styleOverrides as ComponentsOverrides['MuiCssBaseline'], + ); + } else { + overrides[name] = extractV5StateOverrides( + adaptV5Override(theme, component.styleOverrides as V5Override), + ); + } + } + if ('defaultProps' in component) { + props[name] = component.defaultProps; + } + } + + return { overrides, props }; +} diff --git a/packages/theme/src/unified/themes.ts b/packages/theme/src/unified/themes.ts new file mode 100644 index 0000000000..24e1b1026b --- /dev/null +++ b/packages/theme/src/unified/themes.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { palettes } from '../base'; +import { createUnifiedTheme } from './UnifiedTheme'; + +/** + * Built-in Backstage MUI themes. + * + * @public + */ +export const themes = { + light: createUnifiedTheme({ palette: palettes.light }), + dark: createUnifiedTheme({ palette: palettes.dark }), +}; diff --git a/packages/theme/src/unified/types.ts b/packages/theme/src/unified/types.ts new file mode 100644 index 0000000000..f090a99b83 --- /dev/null +++ b/packages/theme/src/unified/types.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A container of one theme for multiple different MUI versions. + * + * Currently known keys are 'v4' and 'v5'. + * + * @public + */ +export interface UnifiedTheme { + getTheme(version: string): unknown | undefined; +} diff --git a/packages/theme/src/v4/baseTheme.ts b/packages/theme/src/v4/baseTheme.ts new file mode 100644 index 0000000000..8143183ec0 --- /dev/null +++ b/packages/theme/src/v4/baseTheme.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Theme as Mui5Theme } from '@mui/material/styles'; +import { createTheme as createMuiTheme } from '@material-ui/core/styles'; +import type { + GridProps, + SwitchProps, + Theme, + ThemeOptions, +} from '@material-ui/core'; +import { Overrides } from '@material-ui/core/styles/overrides'; +import { SimpleThemeOptions } from './types'; +import { createBaseThemeOptions } from '../base'; +import { defaultComponentThemes } from '../v5'; +import { transformV5ComponentThemesToV4 } from '../unified/overrides'; + +/** + * An old helper for creating MUI v4 theme options. + * + * @public + * @deprecated Use {@link createBaseThemeOptions} instead. + */ +export function createThemeOptions(options: SimpleThemeOptions): ThemeOptions { + return { + props: { + MuiGrid: defaultComponentThemes?.MuiGrid + ?.defaultProps as Partial, + MuiSwitch: defaultComponentThemes?.MuiSwitch + ?.defaultProps as Partial, + }, + ...createBaseThemeOptions(options), + }; +} + +/** + * * An old helper for creating MUI v4 theme overrides. + * + * @public + * @deprecated Use {@link defaultComponentThemes} with {@link transformV5ComponentThemesToV4} instead. + */ +export function createThemeOverrides(theme: Theme): Overrides { + return transformV5ComponentThemesToV4( + // Safe but we have to make sure we don't use mui5 specific stuff in the default component themes + theme as unknown as Mui5Theme, + defaultComponentThemes, + ).overrides; +} + +/** + * The old method to create a Backstage MUI v4 theme using a palette. + * The theme is created with the common Backstage options and component styles. + * + * @public + * @deprecated Use {@link createUnifiedTheme} instead. + */ +export function createTheme(options: SimpleThemeOptions): Theme { + const themeOptions = createThemeOptions(options); + const baseTheme = createMuiTheme(themeOptions); + const overrides = createThemeOverrides(baseTheme); + const theme = { ...baseTheme, overrides }; + return theme; +} diff --git a/packages/theme/src/v4/index.ts b/packages/theme/src/v4/index.ts new file mode 100644 index 0000000000..fad349b849 --- /dev/null +++ b/packages/theme/src/v4/index.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { darkTheme, lightTheme } from './themes'; +export { + createTheme, + createThemeOptions, + createThemeOverrides, +} from './baseTheme'; +export type { + BackstagePalette, + BackstagePaletteOptions, + BackstageTheme, + BackstageThemeOptions, + SimpleThemeOptions, +} from './types'; diff --git a/packages/theme/src/v4/themes.ts b/packages/theme/src/v4/themes.ts new file mode 100644 index 0000000000..488ee58831 --- /dev/null +++ b/packages/theme/src/v4/themes.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createTheme } from './baseTheme'; +import { palettes } from '../base'; + +/** + * The old MUI v4 Backstage light theme. + * + * @public + * @deprecated Use {@link themes.light} instead. + */ +export const lightTheme = createTheme({ + palette: palettes.light, +}); + +/** + * The old MUI v4 Backstage dark theme. + * + * @public + * @deprecated Use {@link themes.dark} instead. + */ +export const darkTheme = createTheme({ + palette: palettes.dark, +}); diff --git a/packages/theme/src/v4/types.ts b/packages/theme/src/v4/types.ts new file mode 100644 index 0000000000..8bca5b8c3b --- /dev/null +++ b/packages/theme/src/v4/types.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { + Theme as MuiTheme, + ThemeOptions as MuiThemeOptions, +} from '@material-ui/core'; +import type { + PaletteOptions as MuiPaletteOptions, + Palette as MuiPalette, +} from '@material-ui/core/styles/createPalette'; +import { + BackstagePaletteAdditions, + BackstageThemeAdditions, + PageTheme, + PageThemeSelector, +} from '../base/types'; + +/** + * The full Backstage palette. + * + * @public + * @deprecated This type is deprecated, the MUI Palette type is now always extended instead. + */ +export type BackstagePalette = MuiPalette & BackstagePaletteAdditions; + +/** + * The full Backstage palette options. + * + * @public + * @deprecated This type is deprecated, the MUI PaletteOptions type is now always extended instead. + */ +export type BackstagePaletteOptions = MuiPaletteOptions & + BackstagePaletteAdditions; + +/** + * Backstage theme options. + * + * @public + * @deprecated This type is deprecated, the MUI ThemeOptions type is now always extended instead. + * @remarks + * + * This is essentially a partial theme definition made by the user, that then + * gets merged together with defaults and other values to form the final + * {@link BackstageTheme}. + * + */ +export interface BackstageThemeOptions extends MuiThemeOptions { + palette: BackstagePaletteOptions; + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +} + +/** + * A Backstage theme. + * + * @public + * @deprecated This type is deprecated, the MUI Theme type is now always extended instead. + */ +export interface BackstageTheme extends MuiTheme { + palette: BackstagePalette; + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +} + +/** + * A simpler configuration for creating a new theme that just tweaks some parts + * of the backstage one. + * + * @public + * @deprecated Use {@link BaseThemeOptionsInput} instead. + */ +export type SimpleThemeOptions = { + palette: MuiPaletteOptions; + defaultPageTheme?: string; + pageTheme?: Record; + fontFamily?: string; + htmlFontSize?: number; +}; + +declare module '@material-ui/core/styles/createPalette' { + interface Palette extends BackstagePaletteAdditions {} + + interface PaletteOptions extends BackstagePaletteAdditions {} +} + +declare module '@material-ui/core/styles/createTheme' { + interface Theme extends BackstageThemeAdditions {} + + interface ThemeOptions extends BackstageThemeAdditions {} +} diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/v5/defaultComponentThemes.ts similarity index 50% rename from packages/theme/src/baseTheme.ts rename to packages/theme/src/v5/defaultComponentThemes.ts index c0a9022bd0..14656b007d 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/v5/defaultComponentThemes.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,121 +14,51 @@ * limitations under the License. */ -import { createTheme as createMuiTheme } from '@material-ui/core/styles'; -import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; -import { Overrides } from '@material-ui/core/styles/overrides'; -import { - BackstageTheme, - BackstageThemeOptions, - SimpleThemeOptions, -} from './types'; -import { pageTheme as defaultPageThemes } from './pageTheme'; - -const DEFAULT_HTML_FONT_SIZE = 16; -const DEFAULT_FONT_FAMILY = - '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif'; - -/** - * A helper for creating theme options. - * - * @public - */ -export function createThemeOptions( - options: SimpleThemeOptions, -): BackstageThemeOptions { - const { - palette, - htmlFontSize = DEFAULT_HTML_FONT_SIZE, - fontFamily = DEFAULT_FONT_FAMILY, - defaultPageTheme, - pageTheme = defaultPageThemes, - } = options; - - if (!pageTheme[defaultPageTheme]) { - throw new Error(`${defaultPageTheme} is not defined in pageTheme.`); - } - - return { - palette, - props: { - MuiGrid: { - spacing: 2, - }, - MuiSwitch: { - color: 'primary', - }, - }, - typography: { - htmlFontSize, - fontFamily, - h6: { - fontWeight: 700, - fontSize: 20, - marginBottom: 2, - }, - h5: { - fontWeight: 700, - fontSize: 24, - marginBottom: 4, - }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, - }, - h3: { - fontSize: 32, - fontWeight: 700, - marginBottom: 6, - }, - h2: { - fontSize: 40, - fontWeight: 700, - marginBottom: 8, - }, - h1: { - fontSize: 54, - fontWeight: 700, - marginBottom: 10, - }, - }, - page: pageTheme[defaultPageTheme], - getPageTheme: ({ themeId }) => - pageTheme[themeId] ?? pageTheme[defaultPageTheme], - }; -} +import { darken, lighten, ThemeOptions } from '@mui/material/styles'; /** * A helper for creating theme overrides. * * @public */ -export function createThemeOverrides(theme: BackstageTheme): Overrides { - return { - MuiCssBaseline: { - '@global': { - html: { - height: '100%', - fontFamily: theme.typography.fontFamily, - }, - body: { - height: '100%', - fontFamily: theme.typography.fontFamily, - 'overscroll-behavior-y': 'none', - }, - a: { - color: 'inherit', - textDecoration: 'none', - }, +export const defaultComponentThemes: ThemeOptions['components'] = { + MuiCssBaseline: { + styleOverrides: theme => ({ + html: { + height: '100%', + fontFamily: theme.typography.fontFamily, }, + body: { + height: '100%', + fontFamily: theme.typography.fontFamily, + overscrollBehaviorY: 'none', + fontSize: '0.875rem', + lineHeight: 1.43, + }, + a: { + color: 'inherit', + textDecoration: 'none', + }, + }), + }, + MuiGrid: { + defaultProps: { + spacing: 2, }, - MuiTableRow: { + }, + MuiSwitch: { + defaultProps: { + color: 'primary', + }, + }, + MuiTableRow: { + styleOverrides: { // Alternating row backgrounds - root: { + root: ({ theme }) => ({ '&:nth-of-type(odd)': { backgroundColor: theme.palette.background.default, }, - }, + }), // Use pointer for hoverable rows hover: { '&:hover': { @@ -136,15 +66,17 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { }, }, // Alternating head backgrounds - head: { + head: ({ theme }) => ({ '&:nth-of-type(odd)': { backgroundColor: theme.palette.background.paper, }, - }, + }), }, - // Tables are more dense than default mui tables - MuiTableCell: { - root: { + }, + // Tables are more dense than default mui tables + MuiTableCell: { + styleOverrides: { + root: ({ theme }) => ({ wordBreak: 'break-word', overflow: 'hidden', verticalAlign: 'middle', @@ -152,26 +84,31 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { margin: 0, padding: theme.spacing(3, 2, 3, 2.5), borderBottom: 0, - }, - sizeSmall: { + }), + sizeSmall: ({ theme }) => ({ padding: theme.spacing(1.5, 2, 1.5, 2.5), - }, - head: { + }), + head: ({ theme }) => ({ wordBreak: 'break-word', overflow: 'hidden', + color: theme.palette.textSubtle, fontWeight: 'normal', lineHeight: '1', - }, + }), }, - MuiTabs: { + }, + MuiTabs: { + styleOverrides: { // Tabs are smaller than default mui tab rows root: { minHeight: 24, }, }, - MuiTab: { + }, + MuiTab: { + styleOverrides: { // Tabs are smaller and have a hover background - root: { + root: ({ theme }) => ({ color: theme.palette.link, minHeight: 24, textTransform: 'initial', @@ -185,25 +122,33 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { fontSize: theme.typography.pxToRem(14), fontWeight: 500, }, - }, - textColorPrimary: { + }), + textColorPrimary: ({ theme }) => ({ color: theme.palette.link, - }, + }), }, - MuiTableSortLabel: { + }, + MuiTableSortLabel: { + styleOverrides: { // No color change on hover, just rely on the arrow showing up instead. root: { color: 'inherit', '&:hover': { color: 'inherit', }, - }, - // Bold font for highlighting selected column - active: { - fontWeight: 'bold', + '&:focus': { + color: 'inherit', + }, + // Bold font for highlighting selected column + '&.Mui-active': { + fontWeight: 'bold', + color: 'inherit', + }, }, }, - MuiListItemText: { + }, + MuiListItemText: { + styleOverrides: { dense: { // Default dense list items to adding ellipsis for really long str... whiteSpace: 'nowrap', @@ -211,44 +156,50 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { textOverflow: 'ellipsis', }, }, - MuiButton: { + }, + MuiButton: { + styleOverrides: { text: { // Text buttons have less padding by default, but we want to keep the original padding padding: undefined, }, }, - MuiChip: { - root: { + }, + MuiChip: { + styleOverrides: { + root: ({ theme }) => ({ backgroundColor: '#D9D9D9', // By default there's no margin, but it's usually wanted, so we add some trailing margin marginRight: theme.spacing(1), marginBottom: theme.spacing(1), color: theme.palette.grey[900], - }, - outlined: { + }), + outlined: ({ theme }) => ({ color: theme.palette.text.primary, - }, - label: { - lineHeight: `${theme.spacing(2.5)}px`, + }), + label: ({ theme }) => ({ + lineHeight: theme.spacing(2.5), fontWeight: theme.typography.fontWeightMedium, - fontSize: `${theme.spacing(1.75)}px`, - }, - labelSmall: { - fontSize: `${theme.spacing(1.5)}px`, - }, - deleteIcon: { + fontSize: theme.spacing(1.75), + }), + labelSmall: ({ theme }) => ({ + fontSize: theme.spacing(1.5), + }), + deleteIcon: ({ theme }) => ({ color: theme.palette.grey[500], - width: `${theme.spacing(3)}px`, - height: `${theme.spacing(3)}px`, - margin: `0 ${theme.spacing(0.75)}px 0 -${theme.spacing(0.75)}px`, - }, - deleteIconSmall: { - width: `${theme.spacing(2)}px`, - height: `${theme.spacing(2)}px`, - margin: `0 ${theme.spacing(0.5)}px 0 -${theme.spacing(0.5)}px`, - }, + width: theme.spacing(3), + height: theme.spacing(3), + margin: `0 ${theme.spacing(0.75)} 0 -${theme.spacing(0.75)}`, + }), + deleteIconSmall: ({ theme }) => ({ + width: theme.spacing(2), + height: theme.spacing(2), + margin: `0 ${theme.spacing(0.5)} 0 -${theme.spacing(0.5)}`, + }), }, - MuiCard: { + }, + MuiCard: { + styleOverrides: { root: { // When cards have a forced size, such as when they are arranged in a // CSS grid, the content needs to flex such that the actions (buttons @@ -258,13 +209,17 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { flexDirection: 'column', }, }, - MuiCardHeader: { + }, + MuiCardHeader: { + styleOverrides: { root: { // Reduce padding between header and content paddingBottom: 0, }, }, - MuiCardContent: { + }, + MuiCardContent: { + styleOverrides: { root: { // When cards have a forced size, such as when they are arranged in a // CSS grid, the content needs to flex such that the actions (buttons @@ -276,25 +231,13 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { }, }, }, - MuiCardActions: { + }, + MuiCardActions: { + styleOverrides: { root: { // We default to putting the card actions at the end justifyContent: 'flex-end', }, }, - }; -} - -/** - * Creates a Backstage MUI theme using a palette. The theme is created with the - * common Backstage options and component styles. - * - * @public - */ -export function createTheme(options: SimpleThemeOptions): BackstageTheme { - const themeOptions = createThemeOptions(options); - const baseTheme = createMuiTheme(themeOptions) as BackstageTheme; - const overrides = createThemeOverrides(baseTheme); - const theme = { ...baseTheme, overrides }; - return theme; -} + }, +}; diff --git a/packages/theme/src/v5/index.ts b/packages/theme/src/v5/index.ts new file mode 100644 index 0000000000..eee5d852b1 --- /dev/null +++ b/packages/theme/src/v5/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './types'; +export { defaultComponentThemes } from './defaultComponentThemes'; diff --git a/packages/theme/src/v5/types.ts b/packages/theme/src/v5/types.ts new file mode 100644 index 0000000000..31fe72b5b9 --- /dev/null +++ b/packages/theme/src/v5/types.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Theme } from '@mui/material/styles'; +import { + BackstagePaletteAdditions, + BackstageThemeAdditions, +} from '../base/types'; + +declare module '@mui/material/styles' { + interface Palette extends BackstagePaletteAdditions {} + + interface PaletteOptions extends BackstagePaletteAdditions {} +} + +declare module '@mui/material/styles' { + interface Theme extends BackstageThemeAdditions {} + + interface ThemeOptions extends BackstageThemeAdditions {} +} + +declare module '@mui/private-theming/defaultTheme' { + interface DefaultTheme extends Theme {} +} diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx index 6592c6195e..cc47c8850b 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx @@ -24,7 +24,7 @@ describe('', () => { , ); - expect(baseElement.querySelector('.MuiSvgIcon-root')).toBeInTheDocument(); + expect(baseElement.querySelector('svg')).toBeInTheDocument(); }); it('renders without exploding for unknown kind', async () => { @@ -32,6 +32,6 @@ describe('', () => { , ); - expect(baseElement.querySelector('.MuiSvgIcon-root')).toBeInTheDocument(); + expect(baseElement.querySelector('svg')).toBeInTheDocument(); }); }); diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index e60a96402c..1a921437b1 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -278,7 +278,7 @@ export class TechDocsAddonTester { render(this.build()); }); - const shadowHost = screen.getByTestId('techdocs-native-shadowroot'); + const shadowHost = await screen.findByTestId('techdocs-native-shadowroot'); return { ...screen, diff --git a/yarn.lock b/yarn.lock index 52a508235d..2e6f814cf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2248,7 +2248,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.18.6": +"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-module-imports@npm:7.18.6" dependencies: @@ -2730,7 +2730,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.7.2": +"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.17.12, @babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.18.6 resolution: "@babel/plugin-syntax-jsx@npm:7.18.6" dependencies: @@ -3472,7 +3472,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.21.0 resolution: "@babel/runtime@npm:7.21.0" dependencies: @@ -9627,9 +9627,13 @@ __metadata: resolution: "@backstage/theme@workspace:packages/theme" dependencies: "@backstage/cli": "workspace:^" - "@material-ui/core": ^4.12.2 + "@emotion/react": ^11.10.5 + "@emotion/styled": ^11.10.5 + "@mui/material": ^5.12.2 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: + "@material-ui/core": ^4.12.2 + "@types/react": ^16.13.1 || ^17.0.0 react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 languageName: unknown @@ -10157,6 +10161,41 @@ __metadata: languageName: node linkType: hard +"@emotion/babel-plugin@npm:^11.10.5": + version: 11.10.5 + resolution: "@emotion/babel-plugin@npm:11.10.5" + dependencies: + "@babel/helper-module-imports": ^7.16.7 + "@babel/plugin-syntax-jsx": ^7.17.12 + "@babel/runtime": ^7.18.3 + "@emotion/hash": ^0.9.0 + "@emotion/memoize": ^0.8.0 + "@emotion/serialize": ^1.1.1 + babel-plugin-macros: ^3.1.0 + convert-source-map: ^1.5.0 + escape-string-regexp: ^4.0.0 + find-root: ^1.1.0 + source-map: ^0.5.7 + stylis: 4.1.3 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: e3353499c76c4422d6e900c0dfab73607056d9da86161a3f27c3459c193c4908050c5d252c68fcde231e13f02a9d8e0dc07d260317ae0e5206841e331cc4caae + languageName: node + linkType: hard + +"@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.10.7": + version: 11.10.7 + resolution: "@emotion/cache@npm:11.10.7" + dependencies: + "@emotion/memoize": ^0.8.0 + "@emotion/sheet": ^1.2.1 + "@emotion/utils": ^1.2.0 + "@emotion/weak-memoize": ^0.3.0 + stylis: 4.1.3 + checksum: 6b1efed2dffc93dac419409d91f6d57a200d858ec5ffa4b7c30080fdbd93db431ff86bb779c5b8830b8373f3c5dd754d9beb386604ed2667c7d55608ff653dfc + languageName: node + linkType: hard + "@emotion/hash@npm:^0.8.0": version: 0.8.0 resolution: "@emotion/hash@npm:0.8.0" @@ -10164,19 +10203,93 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.1.0": - version: 1.1.2 - resolution: "@emotion/is-prop-valid@npm:1.1.2" - dependencies: - "@emotion/memoize": ^0.7.4 - checksum: 58b1f2d429a589f8f5bc2c33a8732cbb7bbcb17131a103511ef9a94ac754d7eeb53d627f947da480cd977f9d419fd92e244991680292f3287204159652745707 +"@emotion/hash@npm:^0.9.0": + version: 0.9.0 + resolution: "@emotion/hash@npm:0.9.0" + checksum: b63428f7c8186607acdca5d003700cecf0ded519d0b5c5cc3b3154eafcad6ff433f8361bd2bac8882715b557e6f06945694aeb6ba8b25c6095d7a88570e2e0bb languageName: node linkType: hard -"@emotion/memoize@npm:^0.7.4": - version: 0.7.5 - resolution: "@emotion/memoize@npm:0.7.5" - checksum: 83da8d4a7649a92c72f960817692bc6be13cc13e107b9f7e878d63766525ed4402881bfeb3cda61145c050281e7e260f114a0a2870515527346f2ef896b915b3 +"@emotion/is-prop-valid@npm:^1.1.0, @emotion/is-prop-valid@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/is-prop-valid@npm:1.2.0" + dependencies: + "@emotion/memoize": ^0.8.0 + checksum: cc7a19850a4c5b24f1514665289442c8c641709e6f7711067ad550e05df331da0692a16148e85eda6f47e31b3261b64d74c5e25194d053223be16231f969d633 + languageName: node + linkType: hard + +"@emotion/memoize@npm:^0.8.0": + version: 0.8.0 + resolution: "@emotion/memoize@npm:0.8.0" + checksum: c87bb110b829edd8e1c13b90a6bc37cebc39af29c7599a1e66a48e06f9bec43e8e53495ba86278cc52e7589549492c8dfdc81d19f4fdec0cee6ba13d2ad2c928 + languageName: node + linkType: hard + +"@emotion/react@npm:^11.10.5": + version: 11.10.5 + resolution: "@emotion/react@npm:11.10.5" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.10.5 + "@emotion/cache": ^11.10.5 + "@emotion/serialize": ^1.1.1 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.0 + "@emotion/utils": ^1.2.0 + "@emotion/weak-memoize": ^0.3.0 + hoist-non-react-statics: ^3.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/react": + optional: true + checksum: 32b67b28e9b6d6c53b970072680697f04c2521441050bdeb19a1a7f0164af549b4dad39ff375eda1b6a3cf1cc86ba2c6fa55460ec040e6ebbca3e9ec58353cf7 + languageName: node + linkType: hard + +"@emotion/serialize@npm:^1.1.1": + version: 1.1.1 + resolution: "@emotion/serialize@npm:1.1.1" + dependencies: + "@emotion/hash": ^0.9.0 + "@emotion/memoize": ^0.8.0 + "@emotion/unitless": ^0.8.0 + "@emotion/utils": ^1.2.0 + csstype: ^3.0.2 + checksum: 24cfd5b16e6f2335c032ca33804a876e0442aaf8f9c94d269d23735ebd194fb1ed142542dd92191a3e6ef8bad5bd560dfc5aaf363a1b70954726dbd4dd93085c + languageName: node + linkType: hard + +"@emotion/sheet@npm:^1.2.1": + version: 1.2.1 + resolution: "@emotion/sheet@npm:1.2.1" + checksum: ce78763588ea522438156344d9f592203e2da582d8d67b32e1b0b98eaba26994c6c270f8c7ad46442fc9c0a9f048685d819cd73ca87e544520fd06f0e24a1562 + languageName: node + linkType: hard + +"@emotion/styled@npm:^11.10.5": + version: 11.10.5 + resolution: "@emotion/styled@npm:11.10.5" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.10.5 + "@emotion/is-prop-valid": ^1.2.0 + "@emotion/serialize": ^1.1.1 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.0 + "@emotion/utils": ^1.2.0 + peerDependencies: + "@babel/core": ^7.0.0 + "@emotion/react": ^11.0.0-rc.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/react": + optional: true + checksum: 1cec5f6aeb227a7255141031e8594f38ad83902413472aae0a46c27e5f9769c01e23c1ad39adee408d8a2168a697464314d1a0c4f50b31a5d25ea506b2d7bbc8 languageName: node linkType: hard @@ -10194,6 +10307,36 @@ __metadata: languageName: node linkType: hard +"@emotion/unitless@npm:^0.8.0": + version: 0.8.0 + resolution: "@emotion/unitless@npm:0.8.0" + checksum: 176141117ed23c0eb6e53a054a69c63e17ae532ec4210907a20b2208f91771821835f1c63dd2ec63e30e22fcc984026d7f933773ee6526dd038e0850919fae7a + languageName: node + linkType: hard + +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.0": + version: 1.0.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.0" + peerDependencies: + react: ">=16.8.0" + checksum: 4f06a3b48258c832aa8022a262572061a31ff078d377e9164cccc99951309d70f4466e774fe704461b2f8715007a82ed625a54a5c7a127c89017d3ce3187d4f1 + languageName: node + linkType: hard + +"@emotion/utils@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/utils@npm:1.2.0" + checksum: 55457a49ddd4db6a014ea0454dc09eaa23eedfb837095c8ff90470cb26a303f7ceb5fcc1e2190ef64683e64cfd33d3ba3ca3109cd87d12bc9e379e4195c9a4dd + languageName: node + linkType: hard + +"@emotion/weak-memoize@npm:^0.3.0": + version: 0.3.0 + resolution: "@emotion/weak-memoize@npm:0.3.0" + checksum: f43ef4c8b7de70d9fa5eb3105921724651e4188e895beb71f0c5919dc899a7b8743e1fdd99d38b9092dd5722c7be2312ebb47fbdad0c4e38bea58f6df5885cc0 + languageName: node + linkType: hard + "@esbuild-kit/cjs-loader@npm:^2.4.1": version: 2.4.2 resolution: "@esbuild-kit/cjs-loader@npm:2.4.2" @@ -12734,6 +12877,162 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-alpha.127": + version: 5.0.0-alpha.127 + resolution: "@mui/base@npm:5.0.0-alpha.127" + dependencies: + "@babel/runtime": ^7.21.0 + "@emotion/is-prop-valid": ^1.2.0 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.12.0 + "@popperjs/core": ^2.11.7 + clsx: ^1.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 330baeef1fdaa513707f295e07a3436af24d0831a18109ed877f76b86cf1f392309833d33a2c7ca250db79fdf53f5e88c2618f876f50dbbbf9323bbf08e367e7 + languageName: node + linkType: hard + +"@mui/core-downloads-tracker@npm:^5.12.2": + version: 5.12.2 + resolution: "@mui/core-downloads-tracker@npm:5.12.2" + checksum: d748bdc56df6fdfe6712550a94263cf094c53ddcb70f6a8f633caf23927edf5ac88b1f888429d895fe2a5045b27eb7aa9826ccee5b917e31973667d604ed87fe + languageName: node + linkType: hard + +"@mui/material@npm:^5.12.2": + version: 5.12.2 + resolution: "@mui/material@npm:5.12.2" + dependencies: + "@babel/runtime": ^7.21.0 + "@mui/base": 5.0.0-alpha.127 + "@mui/core-downloads-tracker": ^5.12.2 + "@mui/system": ^5.12.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.12.0 + "@types/react-transition-group": ^4.4.5 + clsx: ^1.2.1 + csstype: ^3.1.2 + prop-types: ^15.8.1 + react-is: ^18.2.0 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: a3464dfbcc496164967e134d6f1d40e060ee02fc2ddb5fcf648ca85580efdbd5eff5aab6a73486d0a7f329f7299127b52501a13993bb131cbd4e310c7f2e633f + languageName: node + linkType: hard + +"@mui/private-theming@npm:^5.12.0": + version: 5.12.0 + resolution: "@mui/private-theming@npm:5.12.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@mui/utils": ^5.12.0 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 761bc7a57e1643c2c4c327886882fa5efc7bacae1c6fffe6be4197f49d337261c916a883d96996445efcdedc0672251725c1e5b264b6250d6c9527fd0cafcc62 + languageName: node + linkType: hard + +"@mui/styled-engine@npm:^5.12.0": + version: 5.12.0 + resolution: "@mui/styled-engine@npm:5.12.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@emotion/cache": ^11.10.7 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.4.1 + "@emotion/styled": ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + checksum: 4a415473cf62aa05012f667dd2e9b1dc2fb175be5b0c4d0b8df541e2dac3d7db410e920e0d5910c8e2b8996a4fb51f74d79483e2878a9b5c0d334498f5537d74 + languageName: node + linkType: hard + +"@mui/system@npm:^5.12.1": + version: 5.12.1 + resolution: "@mui/system@npm:5.12.1" + dependencies: + "@babel/runtime": ^7.21.0 + "@mui/private-theming": ^5.12.0 + "@mui/styled-engine": ^5.12.0 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.12.0 + clsx: ^1.2.1 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: b951959bf5e5af581319354c044f441d97849ff120cfec111d2ed5e7fa05efd63721acff96f48093b8e2bdeb5ccbe35c48613fb925be2b58c596447d10dbed3e + languageName: node + linkType: hard + +"@mui/types@npm:^7.2.4": + version: 7.2.4 + resolution: "@mui/types@npm:7.2.4" + peerDependencies: + "@types/react": "*" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 16bea0547492193a22fd1794382f314698a114f6c673825314c66b56766c3a9d305992cc495684722b7be16a1ecf7e6e48a79caa64f90c439b530e8c02611a61 + languageName: node + linkType: hard + +"@mui/utils@npm:^5.12.0": + version: 5.12.0 + resolution: "@mui/utils@npm:5.12.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^16.7.1 || ^17.0.0 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: 87b2c7468803b083f50af28d7c215c45291e73fef16570848b596d0f1cde1fc613c20e8951f431217b31451de254744abd50eda5013dedec4982420b5bf1c6b6 + languageName: node + linkType: hard + "@n1ru4l/push-pull-async-iterable-iterator@npm:^3.1.0": version: 3.1.0 resolution: "@n1ru4l/push-pull-async-iterable-iterator@npm:3.1.0" @@ -13645,6 +13944,13 @@ __metadata: languageName: node linkType: hard +"@popperjs/core@npm:^2.11.7": + version: 2.11.7 + resolution: "@popperjs/core@npm:2.11.7" + checksum: 5b6553747899683452a1d28898c1b39173a4efd780e74360bfcda8eb42f1c5e819602769c81a10920fc68c881d07fb40429604517d499567eac079cfa6470f19 + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -16489,7 +16795,7 @@ __metadata: languageName: node linkType: hard -"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.3": +"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.3, @types/prop-types@npm:^15.7.5": version: 15.7.5 resolution: "@types/prop-types@npm:15.7.5" checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 @@ -16555,6 +16861,15 @@ __metadata: languageName: node linkType: hard +"@types/react-is@npm:^16.7.1 || ^17.0.0": + version: 17.0.3 + resolution: "@types/react-is@npm:17.0.3" + dependencies: + "@types/react": "*" + checksum: 6abb7c47d54f012272650df8a962a28bd82f219291e5ef8b4dfa7fe0bb98ae243b060bf9fbe8ceff6213141794855a006db194b490b00ffd15842ae19d0ce1f0 + languageName: node + linkType: hard + "@types/react-redux@npm:^7.1.16": version: 7.1.19 resolution: "@types/react-redux@npm:7.1.19" @@ -16603,12 +16918,12 @@ __metadata: languageName: node linkType: hard -"@types/react-transition-group@npm:^4.2.0": - version: 4.2.4 - resolution: "@types/react-transition-group@npm:4.2.4" +"@types/react-transition-group@npm:^4.2.0, @types/react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "@types/react-transition-group@npm:4.4.5" dependencies: "@types/react": "*" - checksum: a8abb3ad3c6e0575c630b591503a78ae3a94e21d1285905a49c36168e5d3de68b0886e2c6d75b751e30f2dc6e4245351cde30e4b3ff2649aec345f2088961e2c + checksum: 265f1c74061556708ffe8d15559e35c60d6c11478c9950d3735575d2c116ca69f461d85effa06d73a613eb8b73c84fd32682feb57cf7c5f9e4284021dbca25b0 languageName: node linkType: hard @@ -18665,6 +18980,17 @@ __metadata: languageName: node linkType: hard +"babel-plugin-macros@npm:^3.1.0": + version: 3.1.0 + resolution: "babel-plugin-macros@npm:3.1.0" + dependencies: + "@babel/runtime": ^7.12.5 + cosmiconfig: ^7.0.0 + resolve: ^1.19.0 + checksum: 765de4abebd3e4688ebdfbff8571ddc8cd8061f839bb6c3e550b0344a4027b04c60491f843296ce3f3379fb356cc873d57a9ee6694262547eb822c14a25be9a6 + languageName: node + linkType: hard + "babel-plugin-polyfill-corejs2@npm:^0.3.1": version: 0.3.1 resolution: "babel-plugin-polyfill-corejs2@npm:0.3.1" @@ -20120,7 +20446,7 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.0.2, clsx@npm:^1.0.4, clsx@npm:^1.1.1": +"clsx@npm:^1.0.2, clsx@npm:^1.0.4, clsx@npm:^1.1.1, clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 @@ -20703,12 +21029,10 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": - version: 1.7.0 - resolution: "convert-source-map@npm:1.7.0" - dependencies: - safe-buffer: ~5.1.1 - checksum: bcd2e3ea7d37f96b85a6e362c8a89402ccc73757256e3ee53aa2c22fe915adb854c66b1f81111be815a3a6a6ce3c58e8001858e883c9d5b4fe08a853fa865967 +"convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 languageName: node linkType: hard @@ -21328,10 +21652,10 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2, csstype@npm:^3.0.6": - version: 3.0.7 - resolution: "csstype@npm:3.0.7" - checksum: 2f30c993be570c6d0de334b979a718370ee9bca9569c90340f13e05e542146c55b22e87372b858c061f9f8ded494da7a4715957882f9356cf9993ba11ab6f09c +"csstype@npm:^3.0.2, csstype@npm:^3.0.6, csstype@npm:^3.1.2": + version: 3.0.9 + resolution: "csstype@npm:3.0.9" + checksum: 199f9af7e673f9f188525c3102a329d637ff46c52f6385a4427ff5cb17adcb736189150170a7af7c5701d18d7704bdad130273f4aa7e44c6c4f9967e6115dc93 languageName: node linkType: hard @@ -25963,7 +26287,7 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.2.1, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.2.1, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -26502,15 +26826,6 @@ __metadata: languageName: node linkType: hard -"indefinite-observable@npm:^2.0.1": - version: 2.0.1 - resolution: "indefinite-observable@npm:2.0.1" - dependencies: - symbol-observable: 1.2.0 - checksum: b4305c999b7596901f8798e569b8faa030361dfb77f8b720e229558a29f544826f7e8987c55cc2a84c37ff2723594a965b96a40a6c71daae92b918f3eb393077 - languageName: node - linkType: hard - "indent-string@npm:^4.0.0": version: 4.0.0 resolution: "indent-string@npm:4.0.0" @@ -28844,76 +29159,76 @@ __metadata: linkType: hard "jss-plugin-camel-case@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-camel-case@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-camel-case@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 hyphenate-style-name: ^1.0.3 - jss: 10.6.0 - checksum: 75c23826deef63c3603cfb47331d1eaf9feeafd097bd115a076f2ee9fb696855d3f18b3f41455a046120fddf0ea11985259c1b8b8a37b3556f4de1a1c83affd5 + jss: 10.9.2 + checksum: 5fa617b23ce9718244691c59ace6a0d1271dbcb4430ce3e13b851ee1879c1db8ecab7e941c33802bea763a0f0e2b609d004b8a975b2063f213cdd639cdd384d2 languageName: node linkType: hard "jss-plugin-default-unit@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-default-unit@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-default-unit@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 - checksum: 7ae36fadf4f206a16e49c40806ef92ba1f0e60395488ab8ad4df96796b408013b38ea5ed975155ecd7833a42a96c8d5cb1e90aef011279816633e60f807ec330 + jss: 10.9.2 + checksum: 48d8d836d36dd15513d98de11fba6be373ac29e6fd5702eb2edd143c815fb9e2f9969b2af6b1b964e9b8a052828690887042f6bcb34836836d5c359e52702d0f languageName: node linkType: hard "jss-plugin-global@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-global@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-global@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 - checksum: 7aab58408c77071c571dd2c2132edad8d40b683513a8de534f0ec7f63926fd9d9fcf6bdda82103eb541452a723b992f061720f8e5cf2014acb7f6bbbde111f56 + jss: 10.9.2 + checksum: 9b29b0c1f169d5a1033890875df072d76364a902d0f6470f448544669a388612a9a4d51844fb2bcb6d25a1c43d67c1637f11a162c2cdd9f4b6b0a8f9c94f6090 languageName: node linkType: hard "jss-plugin-nested@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-nested@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-nested@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 + jss: 10.9.2 tiny-warning: ^1.0.2 - checksum: 38095127e8b5ddb0a33ccaf61a4d89dc1b0f78e6d06d079a47a14bca4aed4e885f1957d83f11c5da08b4249b2c629e8bc62b2996f1674ca1302575a7b2b11171 + checksum: ee08df07f3d553931b48037674842a8314bbc7857cc954a52f962a516bfc4b2d4e9871578b06b8fa3981edf5a927cea00021fd368d4ce315870065b7647f7b57 languageName: node linkType: hard "jss-plugin-props-sort@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-props-sort@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-props-sort@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 - checksum: 2917ff301e667f75efa15df865a860a50d4319d415d1169c213e66b464edc2b37b6f428be2d974ccdde7c8d61c50123f18e788143a96eacc2a1c42ad250ae375 + jss: 10.9.2 + checksum: 70bd181a458a6078f19ad4d7350570c78d26b9aabc25a1fbde673839edcc19825af7b636861b208a38aa17e551e68d0ea38599480716b4aec08e353bbe737222 languageName: node linkType: hard "jss-plugin-rule-value-function@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-rule-value-function@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-rule-value-function@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 + jss: 10.9.2 tiny-warning: ^1.0.2 - checksum: 709e1ce0afdc39a52cb78e371fef626f933e99992790b15771d85056176bdf69365d62cfed6ce95434752cc1a1e7e05a6f2548e4cd5999808d50a28174315be3 + checksum: b1a03209d0249f13ea6de766d3ee14c1769cd1f67d8c543c7d1ce6178c32cf15507c021ecb3e3b7585a8a7a2425dddbe0bdae02f4135c4598725a4152bebfc99 languageName: node linkType: hard "jss-plugin-vendor-prefixer@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-vendor-prefixer@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-vendor-prefixer@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 css-vendor: ^2.0.8 - jss: 10.6.0 - checksum: 9db048022ee2fb79a223a9f1be5976e131715057e3c0200cfcead9b9f8625023942534afa261e3c967cee6ad716bfd7d4a2f356556178f60f4eddcf83bcd8856 + jss: 10.9.2 + checksum: a5c352a500fea82e8a782a090cc9815f6331259f1a331158ed74ed77c750fb45750f5ae95f07d27922742830b45d4c3592cfaab194b3ba4a50591acbdeab04d8 languageName: node linkType: hard @@ -28937,16 +29252,15 @@ __metadata: languageName: node linkType: hard -"jss@npm:10.6.0": - version: 10.6.0 - resolution: "jss@npm:10.6.0" +"jss@npm:10.9.2": + version: 10.9.2 + resolution: "jss@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 csstype: ^3.0.2 - indefinite-observable: ^2.0.1 is-in-browser: ^1.1.3 tiny-warning: ^1.0.2 - checksum: 529edd871ddf059beef55ee0f974ad8436fbcf050d6538e6d2d7edab53ce2c09983d2f863e42a1473dd0e42a0447e9912bce6706bb0e539226d92cdaad128d46 + checksum: 7ae5cd2f8602bf197ec90251d774b9f10d55eb2db0854ac78dc7fb6983828c202e8eb0d5c8c59c73b2f64718ebd33d6063afa799d625a995986a22dc1cc27230 languageName: node linkType: hard @@ -35224,9 +35538,9 @@ __metadata: languageName: node linkType: hard -"react-transition-group@npm:^4.0.0, react-transition-group@npm:^4.4.0": - version: 4.4.1 - resolution: "react-transition-group@npm:4.4.1" +"react-transition-group@npm:^4.0.0, react-transition-group@npm:^4.4.0, react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "react-transition-group@npm:4.4.5" dependencies: "@babel/runtime": ^7.5.5 dom-helpers: ^5.0.1 @@ -35235,7 +35549,7 @@ __metadata: peerDependencies: react: ">=16.6.0" react-dom: ">=16.6.0" - checksum: 0bcd8af483709832e318dcef84c26ebddeb866bf4f58010286367ef0c1e7c5106e00cfc65688b9102414cb3d572c63909c2eb7ea972b4420fc70a78c10b6e8ad + checksum: 75602840106aa9c6545149d6d7ae1502fb7b7abadcce70a6954c4b64a438ff1cd16fc77a0a1e5197cdd72da398f39eb929ea06f9005c45b132ed34e056ebdeb1 languageName: node linkType: hard @@ -37229,6 +37543,13 @@ __metadata: languageName: node linkType: hard +"source-map@npm:^0.5.7": + version: 0.5.7 + resolution: "source-map@npm:0.5.7" + checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d + languageName: node + linkType: hard + "source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.0, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" @@ -38030,10 +38351,10 @@ __metadata: languageName: node linkType: hard -"stylis@npm:^4.0.6": - version: 4.0.7 - resolution: "stylis@npm:4.0.7" - checksum: 4f9fdc4b131b54cdc5988aaf23e796fcf77927c9d2f3147f6b23b8f3a9568eb38ce91b338b9d1b50a50391da32969c34ff68ff971c453fc3a5af89941c60ab06 +"stylis@npm:4.1.3, stylis@npm:^4.0.6": + version: 4.1.3 + resolution: "stylis@npm:4.1.3" + checksum: d04dbffcb9bf2c5ca8d8dc09534203c75df3bf711d33973ea22038a99cc475412a350b661ebd99cbc01daa50d7eedcf0d130d121800eb7318759a197023442a6 languageName: node linkType: hard