diff --git a/packages/threat-composer-app/src/components/NavHeader/index.tsx b/packages/threat-composer-app/src/components/NavHeader/index.tsx index 870c0417..18703e43 100644 --- a/packages/threat-composer-app/src/components/NavHeader/index.tsx +++ b/packages/threat-composer-app/src/components/NavHeader/index.tsx @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ******************************************************************************************************************** */ -import { useNorthStarThemeContext } from '@aws-northstar/ui/components/NorthStarThemeProvider'; +import { useThemeContext } from '@aws/threat-composer'; import TopNavigation, { TopNavigationProps } from '@cloudscape-design/components/top-navigation'; import { Mode, Density } from '@cloudscape-design/global-styles'; import { FC, useMemo } from 'react'; @@ -40,7 +40,7 @@ export interface NavHeaderProps extends Partial { * Top Navigation Header displayed on AppLayout. */ const NavHeader: FC = ({ title, href, logo, ...props }) => { - const { theme, setTheme, density, setDensity } = useNorthStarThemeContext(); + const { theme, setTheme, density, setDensity } = useThemeContext(); const utilities: TopNavigationProps.Utility[] = useMemo(() => { const menu: TopNavigationProps.Utility[] = [ { diff --git a/packages/threat-composer-app/src/config/searchParams.ts b/packages/threat-composer-app/src/config/searchParams.ts index 85b40a05..2d3b7504 100644 --- a/packages/threat-composer-app/src/config/searchParams.ts +++ b/packages/threat-composer-app/src/config/searchParams.ts @@ -13,6 +13,5 @@ See the License for the specific language governing permissions and limitations under the License. ******************************************************************************************************************** */ -export const SEARCH_PARAM_THEME = 'theme'; export const SEARCH_PARAM_MODE = 'mode'; export const SEARCH_PARAM_FEATURES = 'features'; diff --git a/packages/threat-composer-app/src/containers/App/index.tsx b/packages/threat-composer-app/src/containers/App/index.tsx index 519643ac..8bdcf29f 100644 --- a/packages/threat-composer-app/src/containers/App/index.tsx +++ b/packages/threat-composer-app/src/containers/App/index.tsx @@ -30,6 +30,7 @@ const App: FC = () => { const [searchParams] = useSearchParams(); const mode = searchParams.get(SEARCH_PARAM_MODE); const composerMode = mode || DEFAULT_MODE || 'Full'; + return composerMode === 'ThreatsOnly' || composerMode === 'EditorOnly' ? ( ) : ( diff --git a/packages/threat-composer-app/src/index.tsx b/packages/threat-composer-app/src/index.tsx index 94676b60..75f2c5b7 100644 --- a/packages/threat-composer-app/src/index.tsx +++ b/packages/threat-composer-app/src/index.tsx @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ******************************************************************************************************************** */ -import NorthStarThemeProvider from '@aws-northstar/ui/components/NorthStarThemeProvider'; +import { ThemeProvider, Mode } from '@aws/threat-composer'; import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter, MemoryRouter } from 'react-router-dom'; @@ -24,13 +24,19 @@ import isMemoryRouterUsed from './utils/isMemoryRouterUsed'; const Router = isMemoryRouterUsed() ? MemoryRouter : BrowserRouter; +const initialThemeString = (document.querySelector('meta[name="dark-mode"]') as HTMLMetaElement)?.content; + +const initialTheme = initialThemeString ? + (initialThemeString === 'true' ? Mode.Dark : Mode.Light) : + undefined; + ReactDOM.render( - - + + - - + + , document.getElementById('root'), ); diff --git a/packages/threat-composer/.storybook/preview.tsx b/packages/threat-composer/.storybook/preview.tsx index 4c9daef6..686b039a 100644 --- a/packages/threat-composer/.storybook/preview.tsx +++ b/packages/threat-composer/.storybook/preview.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import type { Preview } from "@storybook/react"; import { Mode } from '@cloudscape-design/global-styles'; -import NorthStarThemeProvider from '@aws-northstar/ui/components/NorthStarThemeProvider'; +import ThemeProvider from '../src/components/generic/ThemeProvider'; const preview: Preview = { parameters: { @@ -17,11 +17,11 @@ const preview: Preview = { values: [ { name: 'light', - value: '#ffffff', + value: '#f2f3f3', }, { name: 'dark', - value: '#0f1b2a', + value: '#16191f', }, ], }, @@ -36,8 +36,11 @@ const preview: Preview = { matchColorMode && setColorMode(matchColorMode); }, [args.globals.backgrounds?.value]); - return ( - ); + return ( + + + + ); } ] }; diff --git a/packages/threat-composer/src/components/generic/ThemeProvider/index.tsx b/packages/threat-composer/src/components/generic/ThemeProvider/index.tsx new file mode 100644 index 00000000..6673588c --- /dev/null +++ b/packages/threat-composer/src/components/generic/ThemeProvider/index.tsx @@ -0,0 +1,95 @@ +/** ******************************************************************************************************************* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + + 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 { applyDensity, applyMode, Density, Mode } from '@cloudscape-design/global-styles'; +import { FC, createContext, useState, useEffect, useContext, PropsWithChildren } from 'react'; + +import '@cloudscape-design/global-styles/index.css'; + +export interface ThemeProviderProps { + theme?: Mode; + densitiy?: Density; +} + +export interface ThemeContextApi { + theme: Mode; + density: Density; + setTheme: React.Dispatch>; + setDensity: React.Dispatch>; +} + +const initialState: ThemeContextApi = { + theme: Mode.Light, + density: Density.Comfortable, + setTheme: () => { }, + setDensity: () => { }, +}; + +const ThemeContext = createContext(initialState); + +const ThemeProvider: FC> = ({ + children, + ...props +}) => { + const [theme, setTheme] = useState(() => { + return props.theme || Mode.Light; + }); + + const [density, setDensity] = useState(() => { + if (props.densitiy === Density.Compact) { + return Density.Compact; + } + + return Density.Comfortable; + }); + + useEffect(() => { + typeof props.theme !== 'undefined' && setTheme(props.theme); + }, [props.theme]); + + useEffect(() => { + typeof props.densitiy !== 'undefined' && setDensity(props.densitiy); + }, [props.densitiy]); + + useEffect(() => { + applyMode(theme); + }, [theme]); + + useEffect(() => { + applyDensity(density); + }, [density]); + + return ( + + {children} + + ); +}; + +export { + Mode, + Density, +}; + +export const useThemeContext = () => useContext(ThemeContext); + +export default ThemeProvider; \ No newline at end of file diff --git a/packages/threat-composer/src/components/generic/WindowExporter/index.tsx b/packages/threat-composer/src/components/generic/WindowExporter/index.tsx index 6cc2d848..4677ea09 100644 --- a/packages/threat-composer/src/components/generic/WindowExporter/index.tsx +++ b/packages/threat-composer/src/components/generic/WindowExporter/index.tsx @@ -15,7 +15,7 @@ ******************************************************************************************************************** */ import { useCallback, FC, PropsWithChildren, useEffect } from 'react'; import { useWorkspacesContext } from '../../../contexts'; -import useExportImport from '../../../hooks/useExportImport'; +import useExportImport, { PLACEHOLDER_EXCHANGE_DATA } from '../../../hooks/useExportImport'; import useRemoveData from '../../../hooks/useRemoveData'; /** @@ -34,7 +34,7 @@ const WindowExporter: FC> = ({ children }) => { const setWorkspaceData = useCallback( async (data: any) => { - const parsedData = parseImportedData(data); + const parsedData = parseImportedData(data || PLACEHOLDER_EXCHANGE_DATA); await importData(parsedData); }, [importData], diff --git a/packages/threat-composer/src/components/index.ts b/packages/threat-composer/src/components/index.ts index 61eafc7b..81ec1f02 100644 --- a/packages/threat-composer/src/components/index.ts +++ b/packages/threat-composer/src/components/index.ts @@ -28,3 +28,5 @@ export { default as ThreatPacksComponent } from './workspaces/ThreatPacks'; export { default as ThreatPackComponent } from './workspaces/ThreatPack'; export { default as MitigationPacksComponent } from './workspaces/MitigationPacks'; export { default as MitigationPackComponent } from './workspaces/MitigationPack'; +export { default as ThemeProvider } from './generic/ThemeProvider'; +export * from './generic/ThemeProvider'; \ No newline at end of file diff --git a/packages/threat-composer/src/contexts/GlobalSetupContext/index.tsx b/packages/threat-composer/src/contexts/GlobalSetupContext/index.tsx index 855b46b6..047e9162 100644 --- a/packages/threat-composer/src/contexts/GlobalSetupContext/index.tsx +++ b/packages/threat-composer/src/contexts/GlobalSetupContext/index.tsx @@ -14,11 +14,11 @@ limitations under the License. ******************************************************************************************************************** */ /** @jsxImportSource @emotion/react */ -import { useNorthStarThemeContext } from '@aws-northstar/ui'; import { Mode, Density } from '@cloudscape-design/global-styles'; import { FC, PropsWithChildren, useState, useEffect } from 'react'; import useLocalStorageState from 'use-local-storage-state'; import { GlobalSetupContext, useGlobalSetupContext } from './context'; +import { useThemeContext } from '../../components/generic/ThemeProvider'; import InfoModal from '../../components/global/InfoModal'; import { LOCAL_STORAGE_KEY_NEW_VISIT_FLAG } from '../../configs/localStorageKeys'; import { ComposerMode, DataExchangeFormat } from '../../customTypes'; @@ -56,7 +56,7 @@ const GlobalSetupContextProvider: FC { const [fileImportModalVisible, setFileImportModalVisible] = useState(false); - const { setTheme, setDensity } = useNorthStarThemeContext(); + const { setTheme, setDensity } = useThemeContext(); useEffect(() => { window.threatcomposer.applyDensity = (density?: string) => { diff --git a/packages/threat-composer/src/hooks/useExportImport/index.ts b/packages/threat-composer/src/hooks/useExportImport/index.ts index fea164a1..24f6f321 100644 --- a/packages/threat-composer/src/hooks/useExportImport/index.ts +++ b/packages/threat-composer/src/hooks/useExportImport/index.ts @@ -32,11 +32,10 @@ import recalculateThreatData from '../../utils/recalculateThreatData'; import sanitizeHtml from '../../utils/sanitizeHtml'; import validateData from '../../utils/validateData'; -const PLACEHOLDER_SCHEMA_VERSION = 0; const SCHEMA_VERSION = 1.0; export const PLACEHOLDER_EXCHANGE_DATA = { - schema: PLACEHOLDER_SCHEMA_VERSION, + schema: SCHEMA_VERSION, }; export const PLACEHOLDER_EXCHANGE_DATA_FOR_WORKSPACE = {