Skip to content

Instantly share code, notes, and snippets.

@jxnblk
Created March 23, 2019 00:33
Show Gist options
  • Save jxnblk/ca50d26661f3cfd386e8febe4fb236f2 to your computer and use it in GitHub Desktop.
Save jxnblk/ca50d26661f3cfd386e8febe4fb236f2 to your computer and use it in GitHub Desktop.
import React, { useContext } from 'react'
import { ThemeProvider } from 'emotion-theming'
import { MDXProvider } from '@mdx-js/tag'
import styled from '@emotion/styled'
import merge from 'lodash.merge'
// defaults
const baseTheme = {
colors: {
text: '#345',
background: '#fff',
link: '#07c',
},
}
const baseComponents = {
h1: styled('h1')({
color: 'tomato',
}),
}
const Context = React.createContext()
const mergeThemes = (outer, inner) =>
merge({}, outer, inner)
const noop = n => n
const mergeComponents = (outer, inner, transform = noop) => {
const components = { ...outer }
for (const key in inner) {
const override = inner[key]
components[key] = styled(components[key] || key)(transform(override))
}
return components
}
export const ComponentProvider = ({
theme,
components,
transformStyles = noop,
...props
}) => {
const outer = useContext(Context)
const context = outer ? {
...outer,
theme: mergeThemes(outer.theme, theme),
components: mergeComponents(outer.components, components),
} : {
theme: mergeThemes(baseTheme, theme),
components: mergeComponents(baseComponents, components),
transformStyles,
}
return (
<ThemeProvider theme={context.theme}>
<MDXProvider components={context.components}>
<Context.Provider value={context}>
{props.children}
</Context.Provider>
</MDXProvider>
</ThemeProvider>
)
}
export const useComponents = ({ theme, components } = {}) => {
const context = useContext(Context)
const mergedTheme = mergeThemes(context.theme, theme)
const mergedComponents = mergeComponents(context.components, components)
mergedComponents.theme = mergedTheme
return mergedComponents
}
import React, { useContext } from 'react'
import { ThemeProvider } from 'emotion-theming'
import { MDXProvider } from '@mdx-js/tag'
import styled from '@emotion/styled'
import merge from 'lodash.merge'
const tags = [
]
// defaults
const baseTheme = {
colors: {
text: '#345',
background: '#fff',
link: '#07c',
},
}
const baseComponents = {
h1: styled('h1')({
color: 'tomato',
}),
}
const Context = React.createContext()
const mergeContexts = (outer, inner) => merge({}, outer, inner)
const noop = n => n
const mergeStyles = (components, styles, transform = noop) => {
for (const key in styles) {
const override = styles[key]
components[key] = styled(components[key] || key)(transform(override))
}
return components
}
export const ComponentProvider = ({
theme,
components,
styles,
transformStyles = noop,
...props
}) => {
const outer = useContext(Context)
const context = outer ? {
...outer,
theme: mergeContexts(outer.theme, theme),
components: mergeStyles(
mergeContexts(outer.components, components),
styles,
transformStyles
)
} : {
theme: mergeContexts(baseTheme, theme),
components: mergeStyles(
mergeContexts(baseComponents, components),
styles,
transformStyles
),
transformStyles,
}
return (
<ThemeProvider theme={context.theme}>
<MDXProvider components={context.components}>
<Context.Provider value={context}>
{props.children}
</Context.Provider>
</MDXProvider>
</ThemeProvider>
)
}
export const useComponents = ({ theme, components, styles } = {}) => {
const context = useContext(Context)
const mergedTheme = mergeContexts(context.theme, theme)
const mergedComponents = mergeStyles(
mergeContexts(context.components, components),
styles,
context.transformStyles
)
mergedComponents.theme = mergedTheme
return mergedComponents
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment