-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rewrite themer to use a react context
- Loading branch information
1 parent
64a27f8
commit cf04e13
Showing
14 changed files
with
417 additions
and
346 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Theme } from './utils' | ||
|
||
export declare class Themer { | ||
themeConfig: Theme | ||
|
||
constructor() | ||
|
||
set<TSection extends keyof Theme, TSectionKey extends keyof Theme[TSection]>( | ||
section: TSection, | ||
sectionKey: TSectionKey, | ||
themeValue: string | ||
): void | ||
|
||
subscribe(listener: (themeConfig?: Theme) => void): () => void | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* eslint-disable no-underscore-dangle */ | ||
import { cleanConfig, defaultTheme, themeTemplate, validConfigValue } from './utils' | ||
|
||
export class Themer { | ||
constructor() { | ||
this._themeConfig = defaultTheme | ||
this._onChangeListeners = [] | ||
} | ||
|
||
_callListeners() { | ||
this._onChangeListeners.forEach(listener => { | ||
listener(this._themeConfig) | ||
}) | ||
} | ||
|
||
get themeConfig() { | ||
return this._themeConfig | ||
} | ||
|
||
set themeConfig(themeConfig) { | ||
this._themeConfig = cleanConfig(themeConfig) | ||
this._callListeners() | ||
} | ||
|
||
get(section, sectionKey) { | ||
if (!this._themeConfig) { | ||
console.warn( | ||
'Snacks theme error: No themeConfig defined. Please use Themer template: ', | ||
themeTemplate | ||
) | ||
} else if (validConfigValue(section, sectionKey)) { | ||
return this._themeConfig[section][sectionKey] | ||
} | ||
} | ||
|
||
set(section, sectionKey, themeValue) { | ||
if (validConfigValue(section, sectionKey)) { | ||
this._themeConfig[section][sectionKey] = themeValue | ||
this._callListeners() | ||
} | ||
} | ||
|
||
subscribe(listener) { | ||
this._onChangeListeners.push(listener) | ||
|
||
const unsubscribe = () => { | ||
const index = this._onChangeListeners.indexOf(listener) | ||
if (index === -1) { | ||
return | ||
} | ||
this._onChangeListeners.splice(index, 1) | ||
} | ||
|
||
return unsubscribe | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Context } from 'react' | ||
import { Themer } from './Themer' | ||
|
||
declare interface ThemerContextInterface { | ||
tick: number // for propogating theme updates through react | ||
themer: Themer | ||
} | ||
|
||
export declare const ThemerContext: Context<ThemerContextInterface> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { createContext } from 'react' | ||
import { Themer } from './Themer' | ||
|
||
export const ThemerContext = createContext({ themer: new Themer(), tick: 0 }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import { Themer } from './Themer' | ||
import { ThemerContext } from './ThemerContext' | ||
|
||
export class ThemerProvider extends React.Component { | ||
static propTypes = { | ||
themer: PropTypes.instanceOf(Themer), | ||
children: PropTypes.node, | ||
} | ||
|
||
static contextType = ThemerContext | ||
|
||
state = { | ||
tick: 0, | ||
} | ||
|
||
componentDidMount() { | ||
this.unsubscribe = this.context.themer.subscribe(this.onThemeChange) | ||
} | ||
|
||
componentWillUnmount() { | ||
this.unsubscribe() | ||
} | ||
|
||
onThemeChange = () => { | ||
const { tick } = this.state | ||
// increment tick to force an update on the context | ||
this.setState({ tick: tick + 1 }) | ||
} | ||
|
||
render() { | ||
const { themer, children } = this.props | ||
const { tick } = this.state | ||
return <ThemerContext.Provider value={{ themer, tick }}>{children}</ThemerContext.Provider> | ||
} | ||
} | ||
|
||
ThemerProvider.propTypes = { | ||
themer: PropTypes.object, | ||
children: PropTypes.node, | ||
} |
Oops, something went wrong.