react-native-patina
Advanced tools
+4
-0
| # react-native-patina | ||
| ## 0.1.3 (2020-08-19) | ||
| - (fix) The `ThemeProvider` component would incorrectly provide the initial theme, even if the theme had been changed. | ||
| ## 0.1.2 (2020-08-06) | ||
@@ -4,0 +8,0 @@ |
@@ -31,3 +31,3 @@ import * as React from 'react'; | ||
| */ | ||
| export declare function makeThemeContext<Theme>(theme: Theme): ThemeContext<Theme>; | ||
| export declare function makeThemeContext<Theme>(initialTheme: Theme): ThemeContext<Theme>; | ||
| export {}; |
+15
-18
@@ -6,10 +6,11 @@ import * as React from 'react'; | ||
| */ | ||
| export function makeThemeContext(theme) { | ||
| export function makeThemeContext(initialTheme) { | ||
| let callbacks = []; | ||
| let currentTheme = theme; | ||
| let theme = initialTheme; | ||
| const Context = React.createContext(theme); | ||
| function getTheme() { | ||
| return currentTheme; | ||
| return theme; | ||
| } | ||
| function changeTheme(theme) { | ||
| currentTheme = theme; | ||
| function changeTheme(nextTheme) { | ||
| theme = nextTheme; | ||
| for (let i = 0; i < callbacks.length; ++i) | ||
@@ -24,11 +25,7 @@ callbacks[i](theme); | ||
| } | ||
| const Context = React.createContext(theme); | ||
| /** | ||
| * Provides the current theme to the React component tree. | ||
| */ | ||
| const ThemeProvider = props => { | ||
| const [currentTheme, setCurrentTheme] = React.useState(theme); | ||
| React.useEffect(() => watchTheme(setCurrentTheme), []); | ||
| return (React.createElement(Context.Provider, { value: currentTheme }, props.children)); | ||
| }; | ||
| function ThemeProvider(props) { | ||
| const [themeState, setThemeState] = React.useState(theme); | ||
| React.useEffect(() => watchTheme(setThemeState), []); | ||
| return (React.createElement(Context.Provider, { value: themeState }, props.children)); | ||
| } | ||
| function useTheme() { | ||
@@ -38,7 +35,7 @@ return React.useContext(Context); | ||
| function withTheme(Component) { | ||
| const WithTheme = props => { | ||
| const currentTheme = React.useContext(Context); | ||
| function WithTheme(props) { | ||
| const theme = React.useContext(Context); | ||
| // @ts-expect-error | ||
| return React.createElement(Component, Object.assign({}, props, { theme: currentTheme })); | ||
| }; | ||
| return React.createElement(Component, Object.assign({}, props, { theme: theme })); | ||
| } | ||
| WithTheme.displayName = `WithTheme(${componentName(Component)})`; | ||
@@ -45,0 +42,0 @@ return WithTheme; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"ThemeContext.js","sourceRoot":"","sources":["../src/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqC9B;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAQ,KAAY;IAClD,IAAI,SAAS,GAAgC,EAAE,CAAA;IAC/C,IAAI,YAAY,GAAU,KAAK,CAAA;IAE/B,SAAS,QAAQ;QACf,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,SAAS,WAAW,CAAC,KAAY;QAC/B,YAAY,GAAG,KAAK,CAAA;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YAAE,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAChE,CAAC;IAED,SAAS,UAAU,CAAC,QAA8B;QAChD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACxB,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA;QACzD,CAAC,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAE1C;;OAEG;IACH,MAAM,aAAa,GAAgD,KAAK,CAAC,EAAE;QACzE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC7D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAA;QAEtD,OAAO,CACL,oBAAC,OAAO,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,IAAG,KAAK,CAAC,QAAQ,CAAoB,CAC3E,CAAA;IACH,CAAC,CAAA;IAED,SAAS,QAAQ;QACf,OAAO,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAED,SAAS,SAAS,CAChB,SAAqC;QAErC,MAAM,SAAS,GAAgD,KAAK,CAAC,EAAE;YACrE,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YAC9C,mBAAmB;YACnB,OAAO,oBAAC,SAAS,oBAAK,KAAK,IAAE,KAAK,EAAE,YAAY,IAAI,CAAA;QACtD,CAAC,CAAA;QACD,SAAS,CAAC,WAAW,GAAG,aAAa,aAAa,CAAC,SAAS,CAAC,GAAG,CAAA;QAChE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO;QACL,QAAQ;QACR,WAAW;QACX,UAAU;QACV,aAAa;QACb,QAAQ;QACR,SAAS;KACV,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,SAAmC;IACxD,IAAI,SAAS,CAAC,WAAW,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC,WAAW,CAAA;IAC/D,IAAI,SAAS,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC,IAAI,CAAA;IACjD,OAAO,WAAW,CAAA;AACpB,CAAC"} | ||
| {"version":3,"file":"ThemeContext.js","sourceRoot":"","sources":["../src/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqC9B;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,YAAmB;IAEnB,IAAI,SAAS,GAAgC,EAAE,CAAA;IAC/C,IAAI,KAAK,GAAU,YAAY,CAAA;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAE1C,SAAS,QAAQ;QACf,OAAO,KAAK,CAAA;IACd,CAAC;IAED,SAAS,WAAW,CAAC,SAAgB;QACnC,KAAK,GAAG,SAAS,CAAA;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YAAE,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAChE,CAAC;IAED,SAAS,UAAU,CAAC,QAA8B;QAChD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACxB,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA;QACzD,CAAC,CAAA;IACH,CAAC;IAED,SAAS,aAAa,CAAC,KAAyB;QAC9C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACzD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,CAAA;QAEpD,OAAO,CACL,oBAAC,OAAO,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU,IAAG,KAAK,CAAC,QAAQ,CAAoB,CACzE,CAAA;IACH,CAAC;IAED,SAAS,QAAQ;QACf,OAAO,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAED,SAAS,SAAS,CAChB,SAAqC;QAErC,SAAS,SAAS,CAAC,KAAyB;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YACvC,mBAAmB;YACnB,OAAO,oBAAC,SAAS,oBAAK,KAAK,IAAE,KAAK,EAAE,KAAK,IAAI,CAAA;QAC/C,CAAC;QACD,SAAS,CAAC,WAAW,GAAG,aAAa,aAAa,CAAC,SAAS,CAAC,GAAG,CAAA;QAChE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO;QACL,QAAQ;QACR,WAAW;QACX,UAAU;QACV,aAAa;QACb,QAAQ;QACR,SAAS;KACV,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,SAAmC;IACxD,IAAI,SAAS,CAAC,WAAW,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC,WAAW,CAAA;IAC/D,IAAI,SAAS,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC,IAAI,CAAA;IACjD,OAAO,WAAW,CAAA;AACpB,CAAC"} |
+1
-1
| { | ||
| "name": "react-native-patina", | ||
| "version": "0.1.2", | ||
| "version": "0.1.3", | ||
| "private": false, | ||
@@ -5,0 +5,0 @@ "description": "A simple, type-aware theming library", |
+18
-16
@@ -12,3 +12,3 @@ # react-native-patina | ||
| ```typescript | ||
| ```tsx | ||
| const darkTheme = { | ||
@@ -31,5 +31,7 @@ backgroundColor: '#000000', | ||
| The `ThemeContext` object can help distribute a theme object throughout your app. First, create a `ThemeContext` object based on your initial theme: | ||
| The `ThemeContext` object can help distribute a theme object throughout your app. Compared to just using the React context API directly, `ThemeContext` adds a way for non-React code to also get access to the current theme. This can be important if you have Redux actions or other logic that might also care about appearances. | ||
| ```typescript | ||
| First, create a `ThemeContext` object based on your initial theme: | ||
| ```tsx | ||
| import { makeThemeContext } from 'react-native-patina' | ||
@@ -51,3 +53,3 @@ | ||
| ```typescript | ||
| ```tsx | ||
| const YourApp = () => ( | ||
@@ -62,7 +64,7 @@ <ThemeProvider> | ||
| ```typescript | ||
| ```tsx | ||
| const HeaderText = props => { | ||
| const theme = useTheme() | ||
| // Note: you can use cacheStyles to optimize this: | ||
| // Note: See cacheStyles for how to optimize this: | ||
| const style = { | ||
@@ -78,3 +80,3 @@ color: theme.foregroundColor, | ||
| ```typescript | ||
| ```tsx | ||
| class HeaderTextInner { | ||
@@ -84,3 +86,3 @@ render() { | ||
| // Note: you can use cacheStyles to optimize this: | ||
| // Note: See cacheStyles for how to optimize this: | ||
| const style = { | ||
@@ -99,3 +101,3 @@ color: theme.foregroundColor, | ||
| ```typescript | ||
| ```tsx | ||
| changeTheme(lightTheme) | ||
@@ -108,3 +110,3 @@ ``` | ||
| ```typescript | ||
| ```tsx | ||
| StatusBar.setBackgroundColor(getTheme().statusBarColor) | ||
@@ -115,3 +117,3 @@ ``` | ||
| ```typescript | ||
| ```tsx | ||
| const unsubscribe = watchTheme(theme => { | ||
@@ -130,3 +132,3 @@ StatusBar.setBackgroundColor(theme.statusBarColor) | ||
| ```typescript | ||
| ```tsx | ||
| import { cacheStyles } from 'react-native-patina' | ||
@@ -147,5 +149,5 @@ | ||
| This example uses `cacheStyles` to build a `getStyles` function. This `getStyles` function accepts the current theme and returns a matching set of styles. If the passed-in theme changes, the `getStyles` function automatically calls `StyleSheet.create` and caches the results for future calls: | ||
| This example uses `cacheStyles` to wrap a `getStyles` function with caching. This `getStyles` function accepts the current theme and returns a matching set of styles. From then on, as long as the theme doesn't change, `getStyles` will continue to return the same cached value: | ||
| ```typescript | ||
| ```tsx | ||
| const HeaderText = props => { | ||
@@ -159,5 +161,5 @@ const theme = ThemeContext.useTheme() | ||
| By default, `getStyles` will only remember the last-used theme. If your app frequently switches between several themes (maybe prortrait & landscape modes use separate themes, for instance), you can increase the cache size to keep more than one style sheet around at once: | ||
| By default, `cacheStyles` will only remember the last-used theme. If your app frequently switches between several themes, you can increase the cache size to keep more than one style sheet around at once: | ||
| ```typescript | ||
| ```tsx | ||
| import { setCacheSize } from 'react-native-patina' | ||
@@ -164,0 +166,0 @@ |
+15
-17
@@ -42,12 +42,15 @@ import * as React from 'react' | ||
| */ | ||
| export function makeThemeContext<Theme>(theme: Theme): ThemeContext<Theme> { | ||
| export function makeThemeContext<Theme>( | ||
| initialTheme: Theme | ||
| ): ThemeContext<Theme> { | ||
| let callbacks: Array<WatchCallback<Theme>> = [] | ||
| let currentTheme: Theme = theme | ||
| let theme: Theme = initialTheme | ||
| const Context = React.createContext(theme) | ||
| function getTheme(): Theme { | ||
| return currentTheme | ||
| return theme | ||
| } | ||
| function changeTheme(theme: Theme): void { | ||
| currentTheme = theme | ||
| function changeTheme(nextTheme: Theme): void { | ||
| theme = nextTheme | ||
| for (let i = 0; i < callbacks.length; ++i) callbacks[i](theme) | ||
@@ -63,13 +66,8 @@ } | ||
| const Context = React.createContext(theme) | ||
| function ThemeProvider(props: ThemeProviderProps): JSX.Element { | ||
| const [themeState, setThemeState] = React.useState(theme) | ||
| React.useEffect(() => watchTheme(setThemeState), []) | ||
| /** | ||
| * Provides the current theme to the React component tree. | ||
| */ | ||
| const ThemeProvider: React.FunctionComponent<ThemeProviderProps> = props => { | ||
| const [currentTheme, setCurrentTheme] = React.useState(theme) | ||
| React.useEffect(() => watchTheme(setCurrentTheme), []) | ||
| return ( | ||
| <Context.Provider value={currentTheme}>{props.children}</Context.Provider> | ||
| <Context.Provider value={themeState}>{props.children}</Context.Provider> | ||
| ) | ||
@@ -85,6 +83,6 @@ } | ||
| ): React.ComponentType<RemoveTheme<Props>> { | ||
| const WithTheme: React.FunctionComponent<RemoveTheme<Props>> = props => { | ||
| const currentTheme = React.useContext(Context) | ||
| function WithTheme(props: RemoveTheme<Props>): JSX.Element { | ||
| const theme = React.useContext(Context) | ||
| // @ts-expect-error | ||
| return <Component {...props} theme={currentTheme} /> | ||
| return <Component {...props} theme={theme} /> | ||
| } | ||
@@ -91,0 +89,0 @@ WithTheme.displayName = `WithTheme(${componentName(Component)})` |
157
1.29%20583
-0.13%304
-1.3%