Comparing version 0.1.0 to 1.0.0-rc.1
@@ -1,10 +0,10 @@ | ||
import { Component, Context } from 'react'; | ||
import { Config, ContextLayout } from './interfaces'; | ||
import { Component } from 'react'; | ||
import { Config } from './interfaces'; | ||
interface Props<T extends string | number> { | ||
config: Config<T>; | ||
themeContext: Context<ContextLayout<T>>; | ||
} | ||
export declare class GlobalThemeProvider<T extends string | number> extends Component<Props<T>, { | ||
interface State<T extends string | number> { | ||
theme: T; | ||
}> { | ||
} | ||
export declare class GlobalThemeProvider<T extends string | number> extends Component<Props<T>, State<T>> { | ||
readonly state: { | ||
@@ -16,2 +16,3 @@ theme: T; | ||
}, import("styled-components").DefaultTheme>; | ||
private defaultProps; | ||
render(): JSX.Element; | ||
@@ -18,0 +19,0 @@ private changeTheme; |
@@ -29,3 +29,5 @@ "use strict"; | ||
var styled_components_1 = require("styled-components"); | ||
var constants_1 = require("./constants"); | ||
var helpers_1 = require("./helpers"); | ||
var _1 = require("./"); | ||
var GlobalThemeProvider = /** @class */ (function (_super) { | ||
@@ -39,2 +41,18 @@ __extends(GlobalThemeProvider, _super); | ||
_this.GlobalStyle = styled_components_1.createGlobalStyle(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n\t\t:root {\n\t\t ", "\n\t\t}\n\t"], ["\n\t\t:root {\n\t\t ", "\n\t\t}\n\t"])), function (props) { return helpers_1.getThemes(_this.props.config, props.theme); }); | ||
_this.defaultProps = { | ||
config: { | ||
isPersistent: true | ||
} | ||
}; | ||
_this.changeTheme = function (theme) { | ||
var config = _this.props.config; | ||
if (config.isPersistent) { | ||
var storageKey = _this.props.config.storageKey || constants_1.constants.defaultStorageKey; | ||
localStorage.setItem(storageKey, JSON.stringify(theme)); | ||
} | ||
if (config.onUpdate) { | ||
config.onUpdate(theme); | ||
} | ||
_this.setState({ theme: theme }); | ||
}; | ||
return _this; | ||
@@ -45,3 +63,3 @@ } | ||
var children = this.props.children; | ||
return (react_1.default.createElement(this.props.themeContext.Provider, { value: { | ||
return (react_1.default.createElement(_1.ThemeContext.Provider, { value: { | ||
theme: theme, | ||
@@ -53,6 +71,2 @@ updateTheme: this.changeTheme | ||
}; | ||
GlobalThemeProvider.prototype.changeTheme = function (theme) { | ||
localStorage.setItem('theme-up', JSON.stringify(theme)); | ||
this.setState({ theme: theme }); | ||
}; | ||
return GlobalThemeProvider; | ||
@@ -59,0 +73,0 @@ }(react_1.Component)); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var constants_1 = require("../constants"); | ||
function getDefaultTheme(config) { | ||
@@ -8,8 +9,13 @@ // Catch for Gatsby SSR | ||
} | ||
var userTheme = localStorage.getItem('theme-up'); | ||
if (window.matchMedia('(prefers-color-scheme: dark)').matches && !userTheme) { | ||
userTheme = config.defaultThemeDark; | ||
var storageKey = config.storageKey || constants_1.constants.defaultStorageKey; | ||
var theme = localStorage.getItem(storageKey); | ||
if (window.matchMedia('(prefers-color-scheme: dark)').matches && !theme) { | ||
theme = config.defaultThemeDark; | ||
} | ||
return userTheme || config.defaultTheme; | ||
theme = theme || config.defaultTheme; | ||
if (config.initInterceptor) { | ||
theme = config.initInterceptor(theme); | ||
} | ||
return theme; | ||
} | ||
exports.getDefaultTheme = getDefaultTheme; |
@@ -12,3 +12,3 @@ "use strict"; | ||
var styleKey = _a[_i]; | ||
stylesInterpolation = styled_components_1.css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n\t\t\t\t", ";\n\t\t\t\t", ": ", ";\n\t\t\t"], ["\n\t\t\t\t", ";\n\t\t\t\t", ": ", ";\n\t\t\t"])), stylesInterpolation, styleKey.substr(0, 2) === '--' ? styleKey : "--" + styleKey, styles[styleKey]); | ||
stylesInterpolation = styled_components_1.css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n\t\t\t", ";\n\t\t\t", ": ", ";\n\t\t"], ["\n\t\t\t", ";\n\t\t\t", ": ", ";\n\t\t"])), stylesInterpolation, styleKey.substr(0, 2) === '--' ? styleKey : "--" + styleKey, styles[styleKey]); | ||
} | ||
@@ -15,0 +15,0 @@ return stylesInterpolation; |
@@ -13,4 +13,4 @@ "use strict"; | ||
var themeKey = _a[_i]; | ||
themes = styled_components_1.css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n\t\t\t\t", "\n\t\t\t\t", "\n\t\t\t"], ["\n\t\t\t\t", "\n\t\t\t\t", | ||
"\n\t\t\t"])), themes, theme === themeKey && styled_components_1.css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n\t\t\t\t ", "\n\t\t\t\t"], ["\n\t\t\t\t ", "\n\t\t\t\t"])), getStyles_1.getStyles(config.themes[themeKey]))); | ||
themes = styled_components_1.css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n\t\t\t", "\n\t\t\t", "\n\t\t"], ["\n\t\t\t", "\n\t\t\t", | ||
"\n\t\t"])), themes, theme === themeKey && styled_components_1.css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n\t\t\t\t", "\n\t\t\t"], ["\n\t\t\t\t", "\n\t\t\t"])), getStyles_1.getStyles(config.themes[themeKey]))); | ||
} | ||
@@ -17,0 +17,0 @@ return themes; |
@@ -1,3 +0,3 @@ | ||
export { getThemeContext } from './getThemeContext'; | ||
export { GlobalThemeProvider } from './GlobalThemeProvider'; | ||
export { ContextType, ThemeContext } from './ThemeContext'; | ||
export { Config } from './interfaces'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var getThemeContext_1 = require("./getThemeContext"); | ||
exports.getThemeContext = getThemeContext_1.getThemeContext; | ||
var GlobalThemeProvider_1 = require("./GlobalThemeProvider"); | ||
exports.GlobalThemeProvider = GlobalThemeProvider_1.GlobalThemeProvider; | ||
var ThemeContext_1 = require("./ThemeContext"); | ||
exports.ThemeContext = ThemeContext_1.ThemeContext; |
export interface AdvancedOptions<T> { | ||
themeInitializerInterceptor?: () => T | undefined | null; | ||
initInterceptor?: (theme: T) => T; | ||
onUpdate?: (theme: T) => void; | ||
isPersistent?: boolean; | ||
storageKey?: string; | ||
} |
{ | ||
"name": "theme-up", | ||
"version": "0.1.0", | ||
"version": "1.0.0-rc.1", | ||
"description": "🎨 Easy and persistent theming using the React Context API & CSS variables", | ||
@@ -8,3 +8,3 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"build": "tsc", | ||
"build": "tsc --skipLibCheck", | ||
"lint": "tslint -c tslint.json 'src/**/*.ts{,x}'" | ||
@@ -11,0 +11,0 @@ }, |
@@ -1,2 +0,74 @@ | ||
# theme-up | ||
🎨 Easy persistent theming using the React Context API & CSS variables | ||
<a href="https://www.npmjs.com/package/theme-up"> | ||
<img alt="npm" src="https://img.shields.io/npm/dw/theme-up.svg"> | ||
</a> | ||
<br /> | ||
<br /> | ||
<div align="center"> | ||
<img alt="theme-up logo" src="https://raw.githubusercontent.com/MikeDuister/theme-up/master/logo.png" width="225px" /> | ||
</div> | ||
<br /> | ||
A minimalistic library that allows you to easily add theme support to your React app. | ||
# Installing | ||
1. Add the library to the package.json and install it | ||
```bash | ||
npm install theme-up | ||
``` | ||
2. Make an object of type `Config` (more details in section "Config object") | ||
```TypeScript | ||
import { Config } from 'theme-up' | ||
enum Theme { | ||
Light = 'light', | ||
Dark = 'dark' | ||
} | ||
export const themeConfig: Config<Theme> = { | ||
defaultTheme: Theme.Light, | ||
defaultThemeDark: Theme.Dark, | ||
themes: { | ||
[Theme.Light]: { | ||
backgroundColor: '#FFF', | ||
textColor: '#000' | ||
}, | ||
[Theme.Dark]: { | ||
backgroundColor: '#273238', | ||
textColor: '#FFF' | ||
} | ||
} | ||
} | ||
``` | ||
3. Wrap your app in `GlobalThemeProvider`. | ||
```TypeScript | ||
<GlobalThemeProvider config={themeConfig}> | ||
... | ||
</GlobalThemeProvider> | ||
``` | ||
4. Profit 💰 | ||
# Getting the current theme | ||
1. Import the `ThemeContext` | ||
```typescript | ||
import { ThemeContext } from 'theme-up' | ||
``` | ||
2. Use the Context | ||
3. ? | ||
4. Profit | ||
# Config object | ||
When you're using typescript you should pass your theme identifier as a type. This type can be a string or number, or an extension of them, ex. an Enum (as shown in the installation example). | ||
| key | type | optional | description | | ||
| --- | --- | --- | --- | | ||
| `defaultTheme: T` | generic<sup>*</sup> | required | The default theme. This value must be an object within `themes`. | | ||
| `defaultThemeDark: T` | generic<sup>*</sup> | required | The default theme if the browser specifies a user preference (safari macOS). This value must be an object within `themes`. | | ||
| `themes: { [key in T]?: Styles }` | required | Object, with key as defined in generics | An object containing all themes, every object's key will be used as identifier for that theme. The objects belonging to a theme are key-value pairs defining the variable name and value respectively. The variable names can be written with and without the `--` prefix. | | ||
| `initInterceptor?: (theme: T) => T` | function | optional | Gives you the ability to do something when the theme is initiated (on load). This functions expects a return value of a theme (identifier). | | ||
| `onUpdate?: (theme: T) => void` | function | optional | A function that gets called on every theme change. | | ||
| `isPersistent?: boolean` | boolean | optional | A boolean that decides wether or not the value should be stored and retreived from `localStorage` | | ||
<sup>* an extension of string | number</sup> |
@@ -0,1 +1,2 @@ | ||
import { constants } from '../constants' | ||
import { Config } from '../interfaces' | ||
@@ -9,9 +10,16 @@ | ||
let userTheme: T = localStorage.getItem('theme-up') as T | ||
const storageKey = config.storageKey || constants.defaultStorageKey | ||
let theme: T = localStorage.getItem(storageKey) as T | ||
if (window.matchMedia('(prefers-color-scheme: dark)').matches && !userTheme) { | ||
userTheme = config.defaultThemeDark | ||
if (window.matchMedia('(prefers-color-scheme: dark)').matches && !theme) { | ||
theme = config.defaultThemeDark | ||
} | ||
return userTheme || config.defaultTheme | ||
theme = theme || config.defaultTheme | ||
if (config.initInterceptor) { | ||
theme = config.initInterceptor(theme) | ||
} | ||
return theme | ||
} |
@@ -9,5 +9,5 @@ import { css, FlattenSimpleInterpolation } from 'styled-components' | ||
stylesInterpolation = css` | ||
${stylesInterpolation}; | ||
${styleKey.substr(0, 2) === '--' ? styleKey : `--${styleKey}`}: ${styles[styleKey]}; | ||
` | ||
${stylesInterpolation}; | ||
${styleKey.substr(0, 2) === '--' ? styleKey : `--${styleKey}`}: ${styles[styleKey]}; | ||
` | ||
} | ||
@@ -14,0 +14,0 @@ |
@@ -10,7 +10,7 @@ import { css, FlattenSimpleInterpolation } from 'styled-components' | ||
themes = css` | ||
${themes} | ||
${theme === themeKey && css` | ||
${getStyles(config.themes[themeKey as T] as Styles)} | ||
`} | ||
` | ||
${themes} | ||
${theme === themeKey && css` | ||
${getStyles(config.themes[themeKey as T] as Styles)} | ||
`} | ||
` | ||
} | ||
@@ -17,0 +17,0 @@ |
@@ -1,3 +0,3 @@ | ||
export { getThemeContext } from './getThemeContext' | ||
export { GlobalThemeProvider } from './GlobalThemeProvider' | ||
export { ContextType, ThemeContext } from './ThemeContext' | ||
export { Config } from './interfaces' |
export interface AdvancedOptions<T> { | ||
themeInitializerInterceptor?: () => T | undefined | null | ||
initInterceptor?: (theme: T) => T | ||
onUpdate?: (theme: T) => void | ||
isPersistent?: boolean | ||
storageKey?: string | ||
} |
Sorry, the diff of this file is not supported yet
39844
50
432
75