npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

anoa-react-native-theme

v0.2.1

Published

Theme and stylesheet manager for ReactNative

Downloads

10

Readme

Anoa React Native Theme

Theme and stylesheet manager for ReactNative

Installation

npm i anoa-react-native-theme

Usage

Create Theme(s)

Default Theme

import { createTheme } from 'anoa-react-native-theme'

export const BlueTheme = createTheme(
  // define all theme variables here
  // like color, thickness, radius, etc.
  {
    color: {
      primary: 'blue',
      secondary: 'yellow'
    },
    border: {
      thick: 1,
      bold: 10
    }
  },

  // define named styles using defined theme variables
  vars => ({
    container: {
      padding: 40,
      backgroundColor: vars.color.primary
    },
    button: {
      borderWidth: vars.border.thick,
      backgroundColor: vars.color.secondary
    }
  })
)

Create another theme from Default Theme / child theme (optional)

export const RedTheme = BlueTheme.extend(
  // override default theme variables
  {
    color: {
      primary: 'red',
      secondary: 'green'
    }
  },

  // override default theme style
  vars => ({
    container: {
      padding: 80
    },
    button: {
      borderWidth: vars.border.bold
    }
  })
)

Create Theme Context

import { ThemeContext } from 'anoa-react-native-theme'

export const AppTheme = new ThemeContext(BlueTheme, {
  red: RedTheme

  // define the rest themes you have, eg:
  // green: GreenTheme,
  // yellow: YellowTheme
  // etc ...

  // Notice: all themes defined here must created/extended
  // from default theme or child of default theme.
})

Theme Provider

We are using React Context to provide themes accessibility.

The AppTheme you've created above contains Provider and Consumer property. You have to wrap your root component with Provider to make themes available in every component inside.

export default class App extends Component {
  // ...
  render() {
    return (
      <AppTheme.Provider
        // optional prop to get default theme
        getDefault={async () => {
          // do async operation to get selected theme
          // should returns 'default' or the object key of themes
          // you've defined in the context (eg: 'red' for RedTheme)
          return await MyFancyStorage.getTheme()
        }}
        // optional prop, the event that listen when theme get changed
        onChange={async key => {
          // key returns the 'default' or the object key of themes
          await MyFancyStorage.setTheme(key)
        }}
      >
        <View style={styles.container}>
          <AwesomeComponent />
        </View>
      </AppTheme.Provider>
    )
  }
  // ...
}

Consuming Theme

To consume theme you need to wrap the component with Consumer. Wrapping with Consumer can also be done by using withTheme HOC or withThemeClass class decorator.

Consume theme using AppTheme.Consumer

The Consumer resulting function component with one parameter called theme consists of:

  • vars -- represents current theme variables.

  • styles -- represents current theme named stylesheets.

  • change - a function to change theme.

For more detail, have a look this example:

export class AwesomeComponent extends React.Component {
  // ...

  public render() {
    return (
      <AppTheme.Consumer>
        {({ theme: { vars, styles, change } }) => (
          <View style={styles.container}>
            <Button
              style={styles.button}
              color={vars.color.primary}
              title="Switch to Red Theme"
              onPress={async () => {
                change('red')
              }}
            />

            <Button
              style={theme.styles.button}
              title="Switch to Default Theme"
              onPress={async () => {
                change('default')
              }}
            />
          </View>
        )}
      </AppTheme.Consumer>
    )
  }

  // ...
}

Using withTheme HOC

Use AppTheme.withTheme as HOC (Higher Order Component) that injects theme into your component.

export interface ProfileProps {
  firstName: string
  lastName: string
}

export const Profile = AppTheme.withTheme<ProfileProps>(
  ({ theme, firstName, lastName }) => (
    <View style={theme.styles.container}>
      <Text>{firstName}</Text>
      <Text>{lastName}</Text>
    </View>
  )
)

Using withThemeClass Decorator

If you are fans of class decorator, you can use AppTheme.withThemeClass class decorator to inject theme into your component class.

// Theme props injected into AppThemeProps (see explanation bellow).
// We make it Partial as we won't this props to be required when
// using this component in other component.
export interface LoginProps extends Partial<AppThemeProps> {
  // some props owned by Login component
}

@AppTheme.withThemeClass()
export class Login extends React.Component<LoginProps> {
  constructor(props: LoginProps) {
    super(props)
  }

  public render() {
    // consume theme props, cast it as Required props
    // as it always injected here.
    const { theme } = this.props as Required<LoginProps>

    return (
      <View style={theme.styles.button}>
        <Text style={{ color: theme.vars.color.primary }}>Login</Text>
      </View>
    )
  }
}

AppThemeProps

For typing convenience we need AppThemeProps interface that provides app theme props accessibility. Creating this interface is easily done by:

import { ThemeContextProps } from 'anoa-react-native-theme'

// Use the default theme type (BlueTheme) to presents props values.
export type AppThemeProps = ThemeContextProps<typeof BlueTheme>

Create local stylesheet

The AppTheme also comes with createStyleSheet function that let you create custom local styles for your component using theme variables.

@AppTheme.withThemeClass()
export class About extends React.Component<AboutProps> {
  constructor(props: AboutProps) {
    super(props)
  }

  public render() {
    return (
      <View style={styles.container}>
        <Text>About</Text>
      </View>
    )
  }
}

// create stylesheet based on theme variables
const styles = AppTheme.createStyleSheet(vars => ({
  container: {
    backgroundColor: vars.color.primary,
    padding: 25
  }
}))

License

MIT