From f8c96f0201235568caf64a9b914845fd25957a92 Mon Sep 17 00:00:00 2001 From: atanasster Date: Sun, 2 Aug 2020 09:18:15 -0400 Subject: [PATCH] feat: config update state --- core/store/src/state/context/StateRoot.tsx | 29 ++++--- core/store/src/state/context/store.tsx | 84 ++++++++++++++++++- examples/gatsby/.config/runtime.tsx | 2 +- .../getting-started/ui-customization.mdx | 38 ++++++--- .../src/context/ControlsProvider.tsx | 6 +- .../storybook/src/context/ThemeProvider.tsx | 2 +- .../storybook/src/docs-page/DocsContainer.tsx | 20 ++--- .../storybook/src/panel/AddonPanel.tsx | 8 +- ui/app/src/App/App.stories.tsx | 3 +- ui/app/src/App/App.tsx | 4 +- ui/app/src/AppContext/AppContext.tsx | 24 +++--- .../src/CategoryList/CategoryList.stories.tsx | 3 +- ui/app/src/CategoryList/CategoryList.tsx | 6 +- .../src/CategoryPage/CategoryPage.stories.tsx | 3 +- .../DocumentHomePage.stories.tsx | 3 +- .../DocumentsList/DocumentsList.stories.tsx | 3 +- ui/app/src/Footer/Footer.stories.tsx | 3 +- ui/app/src/Header/Header.stories.tsx | 4 +- ui/app/src/Sidebar/Sidebar.stories.tsx | 3 +- ui/blocks/src/ThemeProvider/ThemeProvider.tsx | 12 +++ ui/blocks/src/ThemeProvider/index.ts | 1 + ui/blocks/src/index.ts | 1 + 22 files changed, 181 insertions(+), 81 deletions(-) create mode 100644 ui/blocks/src/ThemeProvider/ThemeProvider.tsx create mode 100644 ui/blocks/src/ThemeProvider/index.ts diff --git a/core/store/src/state/context/StateRoot.tsx b/core/store/src/state/context/StateRoot.tsx index a6606ad54..cc5353ddd 100644 --- a/core/store/src/state/context/StateRoot.tsx +++ b/core/store/src/state/context/StateRoot.tsx @@ -2,6 +2,7 @@ import React, { FC } from 'react'; import { Store } from '@component-controls/core'; import { StoreContextProvider, + ConfigContextProvider, ActiveTabContextProvider, OptionsContextProvider, } from './store'; @@ -45,19 +46,21 @@ export const StateRoot: FC = ({ }) => { return ( - - - - - - - {children} - - - - - - + + + + + + + + {children} + + + + + + + ); }; diff --git a/core/store/src/state/context/store.tsx b/core/store/src/state/context/store.tsx index 8c8efb6f4..82349c5e3 100644 --- a/core/store/src/state/context/store.tsx +++ b/core/store/src/state/context/store.tsx @@ -1,5 +1,16 @@ -import React, { FC, createContext, useContext } from 'react'; -import { Store, defaultStore, PackageInfo } from '@component-controls/core'; +import React, { + FC, + createContext, + useContext, + useState, + useEffect, +} from 'react'; +import { + Store, + defaultStore, + PackageInfo, + RunConfiguration, +} from '@component-controls/core'; interface StoreContextProps { store: Store; @@ -32,13 +43,78 @@ export const useStore = (): Store => { return store; }; +interface ConfigContextProps { + config: Store['config']; + setConfig: (config: Store['config']) => void; +} + +export const ConfigContext = createContext({ + config: {}, + setConfig: () => {}, +}); + +export const ConfigContextProvider: FC = ({ children }) => { + const store = useStore(); + const [config, setConfig] = useState(store.config); + useEffect(() => { + setConfig(store.config); + }, [store, setConfig]); + + return ( + + {children} + + ); +}; +/** + * Returns a configuration object and the setter method + */ + +export const useConfigState = (): [ + Store['config'], + (config: Store['config']) => void, +] => { + const { config, setConfig } = useContext(ConfigContext); + return [config, setConfig]; +}; + /** * Returns the configuration object part of the store */ export const useConfig = (): Store['config'] => { - const store = useStore(); - return store.config; + const [config] = useConfigState(); + return config; +}; + +/** + * Returns the current theme configuration and a setter method + */ + +export const useThemeState = (): [ + Store['config']['theme'], + (config: Store['config']['theme']) => void, +] => { + const { config, setConfig } = useContext(ConfigContext); + return [ + config.theme, + theme => { + setConfig({ ...config, theme: theme || {} }); + }, + ]; +}; + +/** + * returns current theme object + */ +export const useTheme = (): Store['config']['theme'] => { + const [theme] = useThemeState(); + return theme; }; type ActiveTabType = string | undefined; diff --git a/examples/gatsby/.config/runtime.tsx b/examples/gatsby/.config/runtime.tsx index 741712c6f..02b63283d 100644 --- a/examples/gatsby/.config/runtime.tsx +++ b/examples/gatsby/.config/runtime.tsx @@ -17,7 +17,7 @@ const config: RunOnlyConfiguration = { author: `@component-controls`, theme: { colors: { - //primary: 'pink', + // primary: 'pink', } }, pages: { diff --git a/examples/stories/src/tutorial/getting-started/ui-customization.mdx b/examples/stories/src/tutorial/getting-started/ui-customization.mdx index ae575c744..5b56082b1 100644 --- a/examples/stories/src/tutorial/getting-started/ui-customization.mdx +++ b/examples/stories/src/tutorial/getting-started/ui-customization.mdx @@ -9,10 +9,11 @@ tags: - configuration - theme --- -import { system, funk, future, roboto, dark, deep, swiss, tosh, bootstrap, bulma, tailwind, sketchy } from '@theme-ui/presets'; +import { useEffect } from 'react'; import * as themes from '@theme-ui/presets'; -import { defaultStore, ControlTypes } from '@component-controls/core'; -import { AppContext, App } from '@component-controls/app'; +import { ControlTypes } from '@component-controls/core'; +import { useThemeState } from '@component-controls/store'; +import { Source } from '@component-controls/components'; import { Playground, Story, PropsTable } from '@component-controls/blocks'; @@ -20,16 +21,27 @@ component-controls allows full customization of the user interface - from themin ## Selecting a theme - - - {props => { - const theme = themes[props.theme]; - return ( - - ); - }} - - +You can use any [theme-ui](https://theme-ui.com) theme as a starting point for customizing the user interface. + + + {({ theme: themeName }) => { + const [, setTheme] = useThemeState(); + + useEffect(() => { + console.log(themeName); + setTheme(themes[themeName]) + }, [themeName]); + const theme = themes[themeName]; + return ( + +{`${themeName !== 'none' ? `import { ${themeName} } from '@theme-ui/presets';` : ''} +export default { + theme: ${themeName !== 'none' ? themeName : '{}'}, +}`} + + ); + }} + diff --git a/integrations/storybook/src/context/ControlsProvider.tsx b/integrations/storybook/src/context/ControlsProvider.tsx index c210bd4d9..592599f06 100644 --- a/integrations/storybook/src/context/ControlsProvider.tsx +++ b/integrations/storybook/src/context/ControlsProvider.tsx @@ -4,8 +4,8 @@ import { BlockContextProvider } from './BlockContext'; export const ControlsProvider: React.FC = ({ children }) => { return ( - - {children} - + + {children} + ); }; diff --git a/integrations/storybook/src/context/ThemeProvider.tsx b/integrations/storybook/src/context/ThemeProvider.tsx index 494942523..8b5027e37 100644 --- a/integrations/storybook/src/context/ThemeProvider.tsx +++ b/integrations/storybook/src/context/ThemeProvider.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ThemeProvider as ThemeUIProvider } from '@component-controls/components'; +import { ThemeProvider as ThemeUIProvider } from '@component-controls/blocks'; export const ThemeProvider: React.FC = ({ children }) => { return {children}; diff --git a/integrations/storybook/src/docs-page/DocsContainer.tsx b/integrations/storybook/src/docs-page/DocsContainer.tsx index b9a19feff..95d44a86c 100644 --- a/integrations/storybook/src/docs-page/DocsContainer.tsx +++ b/integrations/storybook/src/docs-page/DocsContainer.tsx @@ -3,7 +3,7 @@ import { PageContainer as BlockPageContainer, BlockContextProvider, } from '@component-controls/blocks'; -import { ThemeProvider } from '@component-controls/components'; +import { ThemeProvider } from '@component-controls/blocks'; import { useCurrentData, getGlobalOptions, @@ -14,18 +14,18 @@ export const PageContextContainer: FC = ({ children }) => { const options = React.useMemo(() => getGlobalOptions(), []); const { storyId, docId } = useCurrentData(); return ( - - + + {children} - - + + ); }; diff --git a/integrations/storybook/src/panel/AddonPanel.tsx b/integrations/storybook/src/panel/AddonPanel.tsx index e58907278..6d60b618d 100644 --- a/integrations/storybook/src/panel/AddonPanel.tsx +++ b/integrations/storybook/src/panel/AddonPanel.tsx @@ -28,10 +28,8 @@ export const AddonPanel: React.FC = ({ }, [api, channel]); const docId = storyId && store ? store.stories[storyId].doc : undefined; return active && storyId ? ( - - - {children} - - + + {children} + ) : null; }; diff --git a/ui/app/src/App/App.stories.tsx b/ui/app/src/App/App.stories.tsx index 8e8e579b0..b31dee894 100644 --- a/ui/app/src/App/App.stories.tsx +++ b/ui/app/src/App/App.stories.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { ThemeProvider } from '@component-controls/components'; -import { MockContext } from '@component-controls/blocks'; +import { ThemeProvider, MockContext } from '@component-controls/blocks'; import { App } from './App'; export default { diff --git a/ui/app/src/App/App.tsx b/ui/app/src/App/App.tsx index 1055b5b79..d5fdff4cb 100644 --- a/ui/app/src/App/App.tsx +++ b/ui/app/src/App/App.tsx @@ -6,6 +6,7 @@ import { useStore, useCurrentDocument, useDocDescription, + useConfig, } from '@component-controls/store'; import { SEO } from '../SEO'; import { Header } from '../Header'; @@ -26,7 +27,8 @@ export interface AppProps { export const App: FC = ({ title = '', children }) => { const store = useStore(); const doc = useCurrentDocument(); - const { toolbar } = store.config || {}; + const config = useConfig(); + const { toolbar } = config; const items: SkiLinksItemProps[] = [ { target: 'content', diff --git a/ui/app/src/AppContext/AppContext.tsx b/ui/app/src/AppContext/AppContext.tsx index 0711f1106..0319ffca5 100644 --- a/ui/app/src/AppContext/AppContext.tsx +++ b/ui/app/src/AppContext/AppContext.tsx @@ -2,13 +2,15 @@ import { FC } from 'react'; import { jsx } from 'theme-ui'; import { Store } from '@component-controls/core'; -import { ThemeProvider } from '@component-controls/components'; import { SidebarContextProvider, LinkContextProvider, LinkContextProviderProps, } from '@component-controls/components'; -import { BlockContextProvider } from '@component-controls/blocks'; +import { + ThemeProvider, + BlockContextProvider, +} from '@component-controls/blocks'; import { App } from '../App'; import { mdxComponents } from './mdxComponents'; @@ -29,19 +31,19 @@ export const AppContext: FC = ({ activeTab, }) => { return ( - - + + {children} - - + + ); }; diff --git a/ui/app/src/CategoryList/CategoryList.stories.tsx b/ui/app/src/CategoryList/CategoryList.stories.tsx index e4ade5c7c..627be3bae 100644 --- a/ui/app/src/CategoryList/CategoryList.stories.tsx +++ b/ui/app/src/CategoryList/CategoryList.stories.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { ThemeProvider } from '@component-controls/components'; -import { MockContext } from '@component-controls/blocks'; +import { ThemeProvider, MockContext } from '@component-controls/blocks'; import { CategoryList } from './CategoryList'; export default { diff --git a/ui/app/src/CategoryList/CategoryList.tsx b/ui/app/src/CategoryList/CategoryList.tsx index 2d0e3ade7..1a06c2311 100644 --- a/ui/app/src/CategoryList/CategoryList.tsx +++ b/ui/app/src/CategoryList/CategoryList.tsx @@ -3,7 +3,7 @@ import { FC } from 'react'; import { jsx, Box } from 'theme-ui'; import { DocType } from '@component-controls/core'; import { Title } from '@component-controls/components'; -import { useDocPropCount, useStore } from '@component-controls/store'; +import { useDocPropCount, useConfig } from '@component-controls/store'; import { PageContainer } from '../PageContainer'; import { CategoryListItem } from './CategoryListItem'; @@ -18,9 +18,9 @@ export interface CategoryListProps { * displays page of categories */ export const CategoryList: FC = ({ type }) => { - const store = useStore(); + const config = useConfig(); const categories = useDocPropCount(type); - const pageConfig = store.config.pages?.[type] || {}; + const pageConfig = config.pages?.[type] || {}; return ( > = props => { + const theme = useTheme(); + console.log(theme); + return ; +}; diff --git a/ui/blocks/src/ThemeProvider/index.ts b/ui/blocks/src/ThemeProvider/index.ts new file mode 100644 index 000000000..8abd195f6 --- /dev/null +++ b/ui/blocks/src/ThemeProvider/index.ts @@ -0,0 +1 @@ +export * from './ThemeProvider'; diff --git a/ui/blocks/src/index.ts b/ui/blocks/src/index.ts index e7dbcd51a..39d475fb4 100644 --- a/ui/blocks/src/index.ts +++ b/ui/blocks/src/index.ts @@ -19,6 +19,7 @@ export * from './StoryConfig'; export * from './StorySource'; export * from './Subtitle'; export * from './TagsList'; +export * from './ThemeProvider'; export * from './Title'; export * from './notifications'; export * from './test';