{"id":13496581,"url":"https://github.com/fahad19/proppy","last_synced_at":"2025-05-16T05:04:31.955Z","repository":{"id":57153818,"uuid":"134983981","full_name":"fahad19/proppy","owner":"fahad19","description":"Functional props composition for UI components (React.js \u0026 Vue.js)","archived":false,"fork":false,"pushed_at":"2019-04-13T22:05:43.000Z","size":1343,"stargazers_count":937,"open_issues_count":13,"forks_count":27,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-05-13T03:01:40.515Z","etag":null,"topics":["functional-programming","javascript","preact","props","react","redux","rxjs","vue"],"latest_commit_sha":null,"homepage":"https://proppyjs.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fahad19.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-26T18:04:01.000Z","updated_at":"2025-01-02T10:37:45.000Z","dependencies_parsed_at":"2022-09-07T12:21:02.706Z","dependency_job_id":null,"html_url":"https://github.com/fahad19/proppy","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fahad19%2Fproppy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fahad19%2Fproppy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fahad19%2Fproppy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fahad19%2Fproppy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fahad19","download_url":"https://codeload.github.com/fahad19/proppy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471060,"owners_count":22076585,"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":["functional-programming","javascript","preact","props","react","redux","rxjs","vue"],"created_at":"2024-07-31T19:01:52.134Z","updated_at":"2025-05-16T05:04:31.937Z","avatar_url":"https://github.com/fahad19.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","📦 Legacy \u0026 Inactive Projects"],"sub_categories":[],"readme":"![ProppyJS](./site/assets/img/banner.png)\n\n\u003cdiv align=\"center\"\u003e\n  \u003cstrong\u003eFunctional props composition for components\u003c/strong\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  A \u003ccode\u003e1.5kB\u003c/code\u003e library integrating with your favourite UI framework\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003c!-- NPM version --\u003e\n  \u003ca href=\"https://npmjs.org/package/proppy\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/proppy.svg?style=flat-square\"\n      alt=\"NPM version\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Build Status --\u003e\n  \u003ca href=\"https://travis-ci.org/fahad19/proppy\"\u003e\n    \u003cimg src=\"https://img.shields.io/travis/fahad19/proppy/master.svg?style=flat-square\"\n      alt=\"Build Status\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Gitter --\u003e\n  \u003ca href=\"https://gitter.im/proppyjs/proppy\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg?style=flat-square\" alt=\"Gitter\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003e\n    \u003ca href=\"https://proppyjs.com\"\u003e\n      Website\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n    \u003ca href=\"https://proppyjs.com/docs/introduction\"\u003e\n      Documentation\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n    \u003ca href=\"https://proppyjs.com/docs/introduction#packages\"\u003e\n      Packages\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n    \u003ca href=\"http://proppyjs.com/docs/contributing/\"\u003e\n      Contributing\n    \u003c/a\u003e\n  \u003c/h3\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003csub\u003eBuilt with ❤︎ by\n  \u003ca href=\"https://twitter.com/fahad19\"\u003e@fahad19\u003c/a\u003e and\n  \u003ca href=\"https://github.com/fahad19/proppy/graphs/contributors\"\u003e\n    contributors\n  \u003c/a\u003e\n\u003c/div\u003e\n\n# What is ProppyJS?\n\nProppyJS is a tiny `1.5kB` JavaScript library for composing props (object that components receive to render themselves).\n\nIt comes with various integration packages giving you the freedom to use it popular rendering libraries.\n\n# What does it do?\n\n[![ProppyJS flow of props](./site/assets/img/proppy-flow.gif)](https://proppyjs.com)\n\nThe idea is you express the behaviour of your Component as props first, and then connect it to your Component (which can be either React, Vue.js or Preact) using the same API of Proppy.\n\nThe API gives you access to other application-wide dependencies too (like a store using Redux) for convenience anywhere in the components tree.\n\n# Packages\n\n| Package              | Status                                                     | Size    | Description               |\n|----------------------|------------------------------------------------------------|---------|---------------------------|\n| [proppy]             | [![proppy-status]][proppy-package]                         | `1.5K`  | Core package              |\n| [proppy-react]       | [![proppy-react-status]][proppy-react-package]             | `1.0K`  | React integration         |\n| [proppy-vue]         | [![proppy-vue-status]][proppy-vue-package]                 | `0.7K`  | Vue.js integration        |\n| [proppy-preact]      | [![proppy-preact-status]][proppy-preact-package]           | `1.1K`  | Preact integration        |\n| [proppy-redux]       | [![proppy-redux-status]][proppy-redux-package]             | `0.6K`  | Redux integration         |\n| [proppy-rx]          | [![proppy-rx-status]][proppy-rx-package]                   | `0.6K`  | RxJS integration          |\n\n[proppy]: https://proppyjs.com/docs/packages/proppy\n[proppy-react]: https://proppyjs.com/docs/packages/proppy-react\n[proppy-vue]: https://proppyjs.com/docs/packages/proppy-vue\n[proppy-preact]: https://proppyjs.com/docs/packages/proppy-preact\n[proppy-redux]: https://proppyjs.com/docs/packages/proppy-redux\n[proppy-rx]: https://proppyjs.com/docs/packages/proppy-rx\n[proppy-frint-react]: https://proppyjs.com/docs/packages/proppy-frint-react\n\n[proppy-status]: https://img.shields.io/npm/v/proppy.svg\n[proppy-react-status]: https://img.shields.io/npm/v/proppy-react.svg\n[proppy-vue-status]: https://img.shields.io/npm/v/proppy-vue.svg\n[proppy-preact-status]: https://img.shields.io/npm/v/proppy-preact.svg\n[proppy-redux-status]: https://img.shields.io/npm/v/proppy-redux.svg\n[proppy-rx-status]: https://img.shields.io/npm/v/proppy-rx.svg\n[proppy-frint-react-status]: https://img.shields.io/npm/v/proppy-frint-react.svg\n\n[proppy-package]: https://npmjs.com/package/proppy\n[proppy-react-package]: https://npmjs.com/package/proppy-react\n[proppy-vue-package]: https://npmjs.com/package/proppy-vue\n[proppy-preact-package]: https://npmjs.com/package/proppy-preact\n[proppy-redux-package]: https://npmjs.com/package/proppy-redux\n[proppy-rx-package]: https://npmjs.com/package/proppy-rx\n[proppy-frint-react-package]: https://npmjs.com/package/proppy-frint-react\n\n# Quick start\n\n- [Installation](#installation)\n- [Basics](#basics)\n  - [Factories](#factories)\n  - [Instances](#instances)\n  - [Subscription](#subscription)\n  - [Destroy](#destroy)\n- [Dynamic props](#dynamic-props)\n- [Composition](#composition)\n- [Providers](#providers)\n- [Rendering with React](#rendering-with-react)\n  - [Set providers](#set-providers)\n  - [Attach factory](#attach-factory)\n\n## Installation\n\nWith [`npm`](https://www.npmjs.com/):\n\n```\n$ npm install --save proppy\n```\n\n## Basics\n\n### Factories\n\nFor the simplicity of this example, we can start with `withProps` function from [`proppy`](https://proppyjs.com/docs/packages/proppy) first:\n\n```js\nimport { withProps } from 'proppy';\n\nconst P = withProps({ counter: 1 });\n```\n\n### Instances\n\nNow we can get an instance from our factory function by calling it:\n\n```js\nconst p = P();\n```\n\nTo access the props synchronously:\n\n```js\nconsole.log(p.props); // { counter: 1 }\n```\n\n### Subscription\n\nGiven the nature of our instance having static props, if we subscribe to it, it will emit the props only once:\n\n```js\nconst unsubscribe = p.subscribe(props =\u003e console.log(props));\n// { counter: 1 }\n```\n\nTo unsubscribe, just call the returned function:\n\n```js\nunsubscribe();\n```\n\n### Destroy\n\nTo cancel all listeners and clear the internal state, just call:\n\n```js\np.destroy();\n```\n\n## Dynamic props\n\nThere are times when your props require a bit of interactivity. Imagine your component wants to render the current state of `counter`, but also want to be able to update the value.\n\nWe can achieve that using the `withState` function for example:\n\n```js\nimport { withState } from 'proppy';\n\n// withState(stateName, setterName, initialState)\nconst P = withState('counter', 'setCounter', 0);\n\nconst p = P();\n```\n\nInitially, the instance will only show you the default initial state for `counter`:\n\n```js\nconsole.log(p.props);\n// { counter: 0, setCounter: Function }\n```\n\nBut we can update it too:\n\n```js\np.props.setCounter(5);\n\nconsole.log(p.props);\n// { counter: 5, setCounter: Function }\n```\n\nIf you subscribed to the instance, it will keep emitting the new props every time a change occurs:\n\n```js\np.subscribe(props =\u003e console.log(props));\n// { counter: 0, setCounter: Function }\n// { counter: 5, setCounter: Function }\n```\n\n## Composition\n\nProppy also ships with a handy `compose` function which allows you to compose multiple factories into a single one:\n\n```js\nimport { compose, withProps, withState } from 'proppy';\n\nconst P = compose(\n  withProps({ foo: 'foo value' }),\n  withProps({ bar: 'bar value' }),\n  withState('counter', 'setCounter', 0)\n);\n```\n\nOnce you create an instance, all the props from those factories will be accessible in a single object:\n\n```js\nconst p = P();\n\nconsole.log(p.props);\n// {\n//   foo: 'foo value',\n//   bar: 'bar value',\n//   counter: 0,\n//   setCounter: Function\n// }\n```\n\n## Providers\n\nProviders are application-wide dependencies that all Proppy instances can access anywhere.\n\nThey are useful especially when you want to maintain them in a single place, but you want Components from anywhere to access them at will.\n\nImagine setting your application's name, in a providers object like this:\n\n```js\nconst myProviders = {\n  appName: 'My Super Awesome App!'\n};\n```\n\nNow when composing your props with Proppy, you want to be able to access them:\n\n```js\nimport { compose, withProps } from 'proppy';\n\nconst P = compose(\n  withProps({ foo: 'foo value' }),\n\n  // `withProps` can also generate props using a function\n  withProps((props, providers) =\u003e {\n    return {\n      name: providers.appname\n    };\n  })\n);\n\n// pass `myProviders` when calling the factory\nconst p = P(myProviders);\n```\n\nYour Proppy instance now has these props:\n\n```js\nconsole.log(p.props);\n// {\n//   foo: 'foo value',\n//   name: 'My Super Awesome App!'\n// }\n```\n\n##  Rendering with React\n\nProppy integrates with React via [`proppy-react`](https://proppyjs.com/docs/packages/proppy-react) package.\n\nYou can install it with `npm` first:\n\n```\n$ npm install --save react proppy-react\n```\n\n### Set providers\n\nThen we need to set our custom providers in our root React component:\n\n```js\n// components/Root.js\nimport React from 'react';\nimport { ProppyProvider } from 'proppy-react';\n\nimport Counter from './Counter';\n\nconst myProviders = {};\n\nexport default function Root() {\n  return (\n    \u003cProppyProvider providers={myProviders}\u003e\n      \u003cCounter /\u003e\n    \u003c/ProppyProvider\u003e\n  );\n}\n```\n\n### Attach factory\n\nNow from anywhere in our components tree, we can use the `attach` higher-order component to connect your Proppy factory to React component:\n\n```js\n// components/Counter.js\nimport React from 'react';\nimport { attach } from 'proppy-react';\nimport { compose, withProps, withState } from 'proppy';\n\nconst P = compose(\n  withProps({ foo: 'foo value' }),\n  withState('counter', 'setCounter', 0),\n);\n\nfunction Counter(props) {\n  const { foo, counter, setCounter } = props;\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eFoo: {foo}\u003c/p\u003e\n\n      \u003cp\u003eCounter: {counter}\u003c/p\u003e\n\n      \u003cbutton onClick={() =\u003e setCounter(counter + 1)}\u003e\n        Increment\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default attach(P)(Counter);\n```\n\nYou can do the same with Vue.js and Preact too via [`proppy-vue`](https://proppyjs.com/docs/packages/proppy-vue) and [`proppy-preact`](https://proppyjs.com/docs/packages/proppy-preact) packages respectively.\n\n# Inspiration\n\nOriginal inspiration for this project has been [`recompose`](https://github.com/acdlite/recompose). If your project is using React, you should definitely check it out.\n\nLearn more about the differences between Proppy and other libraries (like Redux and Recompose) in our [FAQ page](https://proppyjs.com/docs/faq/).\n\n# License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffahad19%2Fproppy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffahad19%2Fproppy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffahad19%2Fproppy/lists"}