{"id":16467313,"url":"https://github.com/elforastero/pulsar-core","last_synced_at":"2025-03-21T06:32:09.734Z","repository":{"id":55501940,"uuid":"312020223","full_name":"ElForastero/pulsar-core","owner":"ElForastero","description":"🚀 Handy dynamic styles utilities for React Native and React Native Web.","archived":false,"fork":false,"pushed_at":"2021-11-07T15:40:32.000Z","size":1289,"stargazers_count":27,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-26T01:21:36.302Z","etag":null,"topics":["dynamicstylesheet","media-queries","pulsar","pulsar-core","react","react-native-web","recat-native","stylesheet","variants"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ElForastero.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-11T16:02:39.000Z","updated_at":"2023-03-25T18:18:52.000Z","dependencies_parsed_at":"2022-08-15T01:50:57.782Z","dependency_job_id":null,"html_url":"https://github.com/ElForastero/pulsar-core","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElForastero%2Fpulsar-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElForastero%2Fpulsar-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElForastero%2Fpulsar-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElForastero%2Fpulsar-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ElForastero","download_url":"https://codeload.github.com/ElForastero/pulsar-core/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244751517,"owners_count":20504242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dynamicstylesheet","media-queries","pulsar","pulsar-core","react","react-native-web","recat-native","stylesheet","variants"],"created_at":"2024-10-11T11:46:56.185Z","updated_at":"2025-03-21T06:32:09.313Z","avatar_url":"https://github.com/ElForastero.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![logo](assets/logo_text.svg)\n\n@pulsar/core\n---\n\n![npm](https://img.shields.io/npm/v/@pulsar/core)\n![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)\n\n\u003e Handy style utilities for React Native and React Native Web.\n\n- 📦 Lightweight (~2 KB)\n- 🚀 Fast (main work happens outside of component)\n- 👌 No dependencies\n- 👮‍♂️ Typed with TypeScript\n- ⚛️ Supports both Native and Web\n\n## What it looks like\n\n```tsx\nimport { DynamicStyleSheet, variants, maxWidth } from '@pulsar/core';\n\n// Use `DynamicStyleSheet` in place of `StyleSheet`.\n// It accepts a function whose first argument is a theme object,\n// and returns styles as it does regular `StyleSheet`.\nconst useStyles = DynamicStyleSheet.create(theme =\u003e ({\n  button: {\n    borderRadius: theme.radii.ios,\n    // You can define any component variations with `variants` helper.\n    ...variants({\n      primary: {\n        backgroundColor: theme.colors.primary\n      },\n      secondary: {\n        backgroundColor: theme.colors.secondary\n      }\n    }),\n    // Media-queries can be used as well.\n    ...maxWidth(theme.breakpoints.tablet, {\n      height: 50\n    })\n  }\n}));\n\nconst Button = ({ children, variant }) =\u003e {\n  // `DynamicStyleSheet` returns a custom react hook.\n  // It has optional parameter - props from which depend variants described above.\n  const styles = useStyles({ variant });\n\n  return (\n    // styles.button here is an array of combined styles\n    \u003cView style={styles.button}\u003e{children}\u003c/View\u003e\n  );\n};\n```\n\n## How is it different?\n\n`@pulsar/core` doesn't call `StyleSheet.create()` during components rendering. All variants and media queries are\nflattened into main object and styles are created once during calling of `DynamicStyleSheet.create()`.\n\nThe result looks like this:\n\n```ts\n// {\n//   'button': {},\n//   '_var:variant:primary:button': {},\n//   '_var:variant:secondary:button': {},\n//   '_media:max-width:768:button': {},\n// }\n```\n\nInstead of calling `StyleSheet.create()` during rendering, the custom hook returned from `DynamicStyleSheet.create()`\njust manipulates with already existing and transpiled styles.\n\nIn the case above `styles.button` will contain an array of\nstyles `[styles['button'], styles['_var:variant:primary:button'], styles['_media:max-width:768:button']]`. So you don't\nhave to worry about merging all those keys together.\n\n## Installation\n\n```sh\nyarn add @pulsar/core\nyarn add --dev babel-plugin-preval\n```\n\nAdd `babel-plugin-preval` to your babel config. Please note that `preval` plugin should be listed first in plugins\narray ([details](https://github.com/kentcdodds/babel-plugin-preval#installation)):\n\n```js\nmodule.exports = {\n  presets: ['module:metro-react-native-babel-preset'],\n  plugins: ['preval'],\n};\n```\n\n## Configuring\n\n1. Import media-queries polyfill in the root of your app. Typically `index.ts`. It's required to emulate media queries\n   in RN.\n\n```ts\nimport '@pulsar/core/dist/polyfill';\n```\n\n2. Overwrite `Theme` interface with your theme shape to enable properties validation and autocompletion. Create a `.d.ts`\n   file, e.g. `pulsar__core.d.ts`.\n\n```ts\n// pulsar__core.d.ts\n\nimport '@pulsar/core';\n\ndeclare module '@pulsar/core' {\n  export interface Theme {\n    // You can define any properties you want.\n    breakpoints: {\n      phone: 320,\n      tablet: 768,\n      desktop: 1280\n    },\n    colors: {\n      primary: string,\n      secondary: string,\n    }\n  }\n}\n```\n\nThen define your light and dark themes using `Theme` interface.\n\n```ts\n// themes/themes.ts\nimport { Theme } from '@pulsar/core';\n\nexport const light: Theme = {\n  breakpoints: {},\n  colors: {}\n}\n```\n\n3. Wrap your app in `\u003cThemeProvider /\u003e`, passing light and dark themes as value. It's required to access the current\n   theme via `useTheme()` hook.\n\n```tsx\nimport { ThemeProvider } from '@pulsar/core';\nimport { lightTheme, darkTheme } from './path/to/your/themes';\n\nconst pulsarConfig = {\n  light: lightTheme,\n  dark: darkTheme,\n}\n\nconst App = () =\u003e (\n  \u003cThemeProvider value={pulsarConfig}\u003e\n    {/* the rest of your app */}\n  \u003c/ThemeProvider\u003e\n)\n```\n\n4. Create `.pulsar.config.js` config file in the root of your project. This config should export light and dark themes\n   and follow the following shape:\n\n```js\n// .pulsar.config.js\nmodule.exports = {\n  themes: {\n    light: { /* your theme definition here */ },\n    dark: { /* your theme definition here */ },\n  }\n}\n```\n\nOr if you have your themes defined somewhere in `src` code, you can just re-export them to pulsar. E.g:\n\n```js\n// .pulsar.config.js\nconst { light } = require('./src/themes/light');\nconst { dark } = require('./src/themes/dark');\n\nmodule.exports = {\n  themes: { light, dark },\n};\n\n```\n\n## Usage\n\nTypical usage of `@pulsar/core` looks like this:\n\n```tsx\nimport { DynamicStyleSheet, variants } from '@pulsar/core';\n\nconst useStyles = DynamicStyleSheet.create(theme =\u003e ({\n  button: {\n    borderRadius: 8,\n    ...variants({\n      primary: {\n        backgroundColor: theme.colors.primary\n      },\n      secondary: {\n        backgroundColor: theme.colors.secondary\n      }\n    })\n  },\n}));\n\nconst Button = ({ children, variant }) =\u003e {\n  const styles = useStyles({ variant });\n\n  return (\n    \u003cView style={s.button}\u003e{children}\u003c/View\u003e\n  )\n};\n```\n\n## Variants\n\nVariants allow defining different component states dependent on its props.\n\n```ts\nimport { DynamicStyleSheet, variants } from '@pulsar/core';\n\nDynamicStyleSheet.create(theme =\u003e ({\n  button: {\n    // Define button size variants\n    ...variants({\n      prop: 'size',\n      variants: {\n        small: {\n          height: 30,\n        },\n        normal: {\n          height: 40,\n        },\n        large: {\n          height: 50,\n        },\n      }\n    }),\n    // Shorthand for `prop = 'variant'`\n    ...variants({\n      primary: {\n        color: theme.colors.primary,\n      },\n      secondary: {\n        color: theme.cosors.secondary,\n      },\n      tertiary: {\n        color: theme.cosors.tertiary,\n      }\n    }),\n    // Arrays can be used as well\n    ...variants([\n      {\n        prop: 'variant', variants: {}\n      },\n      {\n        prop: 'size', variants: {}\n      },\n    ]),\n  }\n}));\n```\n\n## Media Queries\n\nAvailable media-queries:\n\n- minWidth\n- maxWidth\n- minHeight\n- maxHeight\n\n```ts\nimport { DynamicStyleSheet, maxWidth } from '@pulsar/core';\n\nDynamicStyleSheet.create(() =\u003e ({\n  button: {\n    alignSelf: 'flex-start',\n    ...minWidth(768, {\n      alignSelf: 'stretch'\n    });\n  }\n}));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felforastero%2Fpulsar-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felforastero%2Fpulsar-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felforastero%2Fpulsar-core/lists"}