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

@pulsar/core

v0.0.26

Published

```tsx import { DynamicStyleSheet, variants, maxWidth } from '@pulsar/core';

Downloads

11

Readme

logo

@pulsar/core

npm License: MIT

Handy style utilities for React Native and React Native Web.

  • 📦 Lightweight (~2 KB)
  • 🚀 Fast (main work happens outside of component)
  • 👌 No dependencies
  • 👮‍♂️ Typed with TypeScript
  • ⚛️ Supports both Native and Web

What it looks like

import { DynamicStyleSheet, variants, maxWidth } from '@pulsar/core';

// Use `DynamicStyleSheet` in place of `StyleSheet`.
// It accepts a function whose first argument is a theme object,
// and returns styles as it does regular `StyleSheet`.
const useStyles = DynamicStyleSheet.create(theme => ({
  button: {
    borderRadius: theme.radii.ios,
    // You can define any component variations with `variants` helper.
    ...variants({
      primary: {
        backgroundColor: theme.colors.primary
      },
      secondary: {
        backgroundColor: theme.colors.secondary
      }
    }),
    // Media-queries can be used as well.
    ...maxWidth(theme.breakpoints.tablet, {
      height: 50
    })
  }
}));

const Button = ({ children, variant }) => {
  // `DynamicStyleSheet` returns a custom react hook.
  // It has optional parameter - props from which depend variants described above.
  const styles = useStyles({ variant });

  return (
    // styles.button here is an array of combined styles
    <View style={styles.button}>{children}</View>
  );
};

How is it different?

@pulsar/core doesn't call StyleSheet.create() during components rendering. All variants and media queries are flattened into main object and styles are created once during calling of DynamicStyleSheet.create().

The result looks like this:

// {
//   'button': {},
//   '_var:variant:primary:button': {},
//   '_var:variant:secondary:button': {},
//   '_media:max-width:768:button': {},
// }

Instead of calling StyleSheet.create() during rendering, the custom hook returned from DynamicStyleSheet.create() just manipulates with already existing and transpiled styles.

In the case above styles.button will contain an array of styles [styles['button'], styles['_var:variant:primary:button'], styles['_media:max-width:768:button']]. So you don't have to worry about merging all those keys together.

Installation

yarn add @pulsar/core
yarn add --dev babel-plugin-preval

Add babel-plugin-preval to your babel config. Please note that preval plugin should be listed first in plugins array (details):

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: ['preval'],
};

Configuring

  1. Import media-queries polyfill in the root of your app. Typically index.ts. It's required to emulate media queries in RN.
import '@pulsar/core/dist/polyfill';
  1. Overwrite Theme interface with your theme shape to enable properties validation and autocompletion. Create a .d.ts file, e.g. pulsar__core.d.ts.
// pulsar__core.d.ts

import '@pulsar/core';

declare module '@pulsar/core' {
  export interface Theme {
    // You can define any properties you want.
    breakpoints: {
      phone: 320,
      tablet: 768,
      desktop: 1280
    },
    colors: {
      primary: string,
      secondary: string,
    }
  }
}

Then define your light and dark themes using Theme interface.

// themes/themes.ts
import { Theme } from '@pulsar/core';

export const light: Theme = {
  breakpoints: {},
  colors: {}
}
  1. Wrap your app in <ThemeProvider />, passing light and dark themes as value. It's required to access the current theme via useTheme() hook.
import { ThemeProvider } from '@pulsar/core';
import { lightTheme, darkTheme } from './path/to/your/themes';

const pulsarConfig = {
  light: lightTheme,
  dark: darkTheme,
}

const App = () => (
  <ThemeProvider value={pulsarConfig}>
    {/* the rest of your app */}
  </ThemeProvider>
)
  1. Create .pulsar.config.js config file in the root of your project. This config should export light and dark themes and follow the following shape:
// .pulsar.config.js
module.exports = {
  themes: {
    light: { /* your theme definition here */ },
    dark: { /* your theme definition here */ },
  }
}

Or if you have your themes defined somewhere in src code, you can just re-export them to pulsar. E.g:

// .pulsar.config.js
const { light } = require('./src/themes/light');
const { dark } = require('./src/themes/dark');

module.exports = {
  themes: { light, dark },
};

Usage

Typical usage of @pulsar/core looks like this:

import { DynamicStyleSheet, variants } from '@pulsar/core';

const useStyles = DynamicStyleSheet.create(theme => ({
  button: {
    borderRadius: 8,
    ...variants({
      primary: {
        backgroundColor: theme.colors.primary
      },
      secondary: {
        backgroundColor: theme.colors.secondary
      }
    })
  },
}));

const Button = ({ children, variant }) => {
  const styles = useStyles({ variant });

  return (
    <View style={s.button}>{children}</View>
  )
};

Variants

Variants allow defining different component states dependent on its props.

import { DynamicStyleSheet, variants } from '@pulsar/core';

DynamicStyleSheet.create(theme => ({
  button: {
    // Define button size variants
    ...variants({
      prop: 'size',
      variants: {
        small: {
          height: 30,
        },
        normal: {
          height: 40,
        },
        large: {
          height: 50,
        },
      }
    }),
    // Shorthand for `prop = 'variant'`
    ...variants({
      primary: {
        color: theme.colors.primary,
      },
      secondary: {
        color: theme.cosors.secondary,
      },
      tertiary: {
        color: theme.cosors.tertiary,
      }
    }),
    // Arrays can be used as well
    ...variants([
      {
        prop: 'variant', variants: {}
      },
      {
        prop: 'size', variants: {}
      },
    ]),
  }
}));

Media Queries

Available media-queries:

  • minWidth
  • maxWidth
  • minHeight
  • maxHeight
import { DynamicStyleSheet, maxWidth } from '@pulsar/core';

DynamicStyleSheet.create(() => ({
  button: {
    alignSelf: 'flex-start',
    ...minWidth(768, {
      alignSelf: 'stretch'
    });
  }
}));