|
1 | | -# TSDX React User Guide |
| 1 | +# React-pluggable |
2 | 2 |
|
3 | | -Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it. |
| 3 | +React-pluggable is a library that helps you develop your react application on the plugin model. |
4 | 4 |
|
5 | | -> This TSDX setup is meant for developing React component libraries (not apps!) that can be published to NPM. If you’re looking to build a React-based app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`. |
| 5 | +## Installation |
6 | 6 |
|
7 | | -> If you’re new to TypeScript and React, checkout [this handy cheatsheet](https://github.com/sw-yx/react-typescript-cheatsheet/) |
8 | | -
|
9 | | -## Commands |
10 | | - |
11 | | -TSDX scaffolds your new library inside `/src`, and also sets up a [Parcel-based](https://parceljs.org) playground for it inside `/example`. |
12 | | - |
13 | | -The recommended workflow is to run TSDX in one terminal: |
14 | | - |
15 | | -```bash |
16 | | -npm start # or yarn start |
17 | | -``` |
18 | | - |
19 | | -This builds to `/dist` and runs the project in watch mode so any edits you save inside `src` causes a rebuild to `/dist`. |
20 | | - |
21 | | -Then run the example inside another: |
| 7 | +Use npm or yarn to install this to your application. |
22 | 8 |
|
23 | 9 | ```bash |
24 | | -cd example |
25 | | -npm i # or yarn to install dependencies |
26 | | -npm start # or yarn start |
| 10 | +yarn add react-pluggable |
27 | 11 | ``` |
28 | 12 |
|
29 | | -The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases). |
| 13 | +## Usage |
30 | 14 |
|
31 | | -To do a one-off build, use `npm run build` or `yarn build`. |
| 15 | +### Making a plugin |
32 | 16 |
|
33 | | -To run tests, use `npm test` or `yarn test`. |
| 17 | +##### ClickMePlugin.tsx |
34 | 18 |
|
35 | | -## Configuration |
| 19 | +```tsx |
| 20 | +import React from 'react'; |
| 21 | +import { IPlugin } from 'react-pluggable'; |
36 | 22 |
|
37 | | -Code quality is set up for you with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. |
| 23 | +class ClickMePlugin implements IPlugin { |
| 24 | + public pluginStore; |
38 | 25 |
|
39 | | -### Jest |
| 26 | + init(pluginStore) { |
| 27 | + this.pluginStore = pluginStore; |
| 28 | + } |
40 | 29 |
|
41 | | -Jest tests are set up to run with `npm test` or `yarn test`. |
| 30 | + activate() { |
| 31 | + this.pluginStore.addFunction('sendAlert', () => { |
| 32 | + alert('Testing'); |
| 33 | + }); |
42 | 34 |
|
43 | | -#### Setup Files |
| 35 | + this.pluginStore.executeFunction('RendererPlugin.add', 'top', () => ( |
| 36 | + <h1>This is an element from the plugin</h1> |
| 37 | + )); |
| 38 | + } |
44 | 39 |
|
45 | | -This is the folder structure we set up for you: |
| 40 | + deactivate() { |
| 41 | + // |
| 42 | + } |
| 43 | +} |
46 | 44 |
|
47 | | -```txt |
48 | | -/example |
49 | | - index.html |
50 | | - index.tsx # test your component here in a demo app |
51 | | - package.json |
52 | | - tsconfig.json |
53 | | -/src |
54 | | - index.tsx # EDIT THIS |
55 | | -/test |
56 | | - blah.test.tsx # EDIT THIS |
57 | | -.gitignore |
58 | | -package.json |
59 | | -README.md # EDIT THIS |
60 | | -tsconfig.json |
| 45 | +export default ClickMePlugin; |
61 | 46 | ``` |
62 | 47 |
|
63 | | -#### React Testing Library |
64 | | - |
65 | | -We do not set up `react-testing-library` for you yet, we welcome contributions and documentation on this. |
66 | | - |
67 | | -### Rollup |
68 | | - |
69 | | -TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. |
70 | | - |
71 | | -### TypeScript |
72 | | - |
73 | | -`tsconfig.json` is set up to interpret `dom` and `esnext` types, as well as `react` for `jsx`. Adjust according to your needs. |
| 48 | +### Adding it to your app |
74 | 49 |
|
75 | | -## Continuous Integration |
| 50 | +##### App.tsx |
76 | 51 |
|
77 | | -### GitHub Actions |
| 52 | +```tsx |
| 53 | +import * as React from 'react'; |
| 54 | +import * as ReactDOM from 'react-dom'; |
| 55 | +import { createPluginStore, PluginProvider } from 'react-pluggable'; |
| 56 | +import ClickMePlugin from './Plugins/ClickMePlugin'; |
| 57 | +import Test from './components/Test'; |
78 | 58 |
|
79 | | -A simple action is included that runs these steps on all pushes: |
| 59 | +const pluginStore = createPluginStore(); |
| 60 | +pluginStore.install('ClickMePlugin', new ClickMePlugin()); |
80 | 61 |
|
81 | | -- Installs deps w/ cache |
82 | | -- Lints, tests, and builds |
| 62 | +const App = () => { |
| 63 | + pluginStore.addFunction('test', (a, b) => { |
| 64 | + console.log('working', a, b); |
| 65 | + }); |
| 66 | + return ( |
| 67 | + <PluginProvider pluginStore={pluginStore}> |
| 68 | + <Test></Test> |
| 69 | + </PluginProvider> |
| 70 | + ); |
| 71 | +}; |
83 | 72 |
|
84 | | -## Optimizations |
85 | | - |
86 | | -Please see the main `tsdx` [optimizations docs](https://github.com/palmerhq/tsdx#optimizations). In particular, know that you can take advantage of development-only optimizations: |
87 | | - |
88 | | -```js |
89 | | -// ./types/index.d.ts |
90 | | -declare var __DEV__: boolean; |
91 | | - |
92 | | -// inside your code... |
93 | | -if (__DEV__) { |
94 | | - console.log('foo'); |
95 | | -} |
| 73 | +ReactDOM.render(<App />, document.getElementById('root')); |
96 | 74 | ``` |
97 | 75 |
|
98 | | -You can also choose to install and use [invariant](https://github.com/palmerhq/tsdx#invariant) and [warning](https://github.com/palmerhq/tsdx#warning) functions. |
99 | | - |
100 | | -## Module Formats |
101 | | - |
102 | | -CJS, ESModules, and UMD module formats are supported. |
| 76 | +### Using the plugin |
| 77 | + |
| 78 | +##### Test.tsx |
| 79 | + |
| 80 | +```tsx |
| 81 | +import * as React from 'react'; |
| 82 | +import { usePluginStore } from 'react-pluggable'; |
| 83 | + |
| 84 | +const Test = (props: any) => { |
| 85 | + const pluginStore: any = usePluginStore(); |
| 86 | + |
| 87 | + pluginStore.executeFunction('test', 1, 2); |
| 88 | + return ( |
| 89 | + <> |
| 90 | + <h1>Working</h1>{' '} |
| 91 | + <button |
| 92 | + onClick={() => { |
| 93 | + pluginStore.executeFunction('sendAlert'); |
| 94 | + }} |
| 95 | + > |
| 96 | + Send Alert |
| 97 | + </button> |
| 98 | + </> |
| 99 | + ); |
| 100 | +}; |
| 101 | + |
| 102 | +export default Test; |
| 103 | +``` |
103 | 104 |
|
104 | | -The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please report if any issues are found. |
| 105 | +### Using the inbuilt renderer |
105 | 106 |
|
106 | | -## Deploying the Example Playground |
| 107 | +Sometimes a plugin has an UI component associated with it. You can implement this functionality by simply building a plugin of your own or using the default plugin provided by the package. |
107 | 108 |
|
108 | | -The Playground is just a simple [Parcel](https://parceljs.org) app, you can deploy it anywhere you would normally deploy that. Here are some guidelines for **manually** deploying with the Netlify CLI (`npm i -g netlify-cli`): |
| 109 | +You can add the inbuilt renderer plugin by importing and installing `RendererPlugin` provided in the package. |
109 | 110 |
|
110 | | -```bash |
111 | | -cd example # if not already in the example folder |
112 | | -npm run build # builds to dist |
113 | | -netlify deploy # deploy the dist folder |
114 | | -``` |
| 111 | +#### Importing the plugin |
115 | 112 |
|
116 | | -Alternatively, if you already have a git repo connected, you can set up continuous deployment with Netlify: |
| 113 | +##### App.tsx |
117 | 114 |
|
118 | | -```bash |
119 | | -netlify init |
120 | | -# build command: yarn build && cd example && yarn && yarn build |
121 | | -# directory to deploy: example/dist |
122 | | -# pick yes for netlify.toml |
| 115 | +```tsx |
| 116 | +import * as React from 'react'; |
| 117 | +import { usePluginStore } from 'react-pluggable'; |
123 | 118 | ``` |
124 | 119 |
|
125 | | -## Named Exports |
126 | | - |
127 | | -Per Palmer Group guidelines, [always use named exports.](https://github.com/palmerhq/typescript#exports) Code split inside your React app instead of your React library. |
| 120 | +##### Test.tsx |
128 | 121 |
|
129 | | -## Including Styles |
| 122 | +```tsx |
| 123 | +import * as React from 'react'; |
| 124 | +import { usePluginStore } from 'react-pluggable'; |
130 | 125 |
|
131 | | -There are many ways to ship styles, including with CSS-in-JS. TSDX has no opinion on this, configure how you like. |
| 126 | +const Test = (props: any) => { |
| 127 | + const pluginStore: any = usePluginStore(); |
132 | 128 |
|
133 | | -For vanilla CSS, you can include it at the root directory and add it to the `files` section in your `package.json`, so that it can be imported separately by your users and run through their bundler's loader. |
| 129 | + pluginStore.executeFunction('test', 1, 2); |
| 130 | + let Renderer = pluginStore.executeFunction( |
| 131 | + 'RendererPlugin.getRendererComponent' |
| 132 | + ); |
| 133 | + return ( |
| 134 | + <> |
| 135 | + <Renderer placement={'top'} /> |
| 136 | + </> |
| 137 | + ); |
| 138 | +}; |
134 | 139 |
|
135 | | -## Publishing to NPM |
136 | | - |
137 | | -We recommend using [np](https://github.com/sindresorhus/np). |
| 140 | +export default Test; |
| 141 | +``` |
138 | 142 |
|
139 | | -## Usage with Lerna |
| 143 | +--- |
140 | 144 |
|
141 | | -When creating a new package with TSDX within a project set up with Lerna, you might encounter a `Cannot resolve dependency` error when trying to run the `example` project. To fix that you will need to make changes to the `package.json` file _inside the `example` directory_. |
| 145 | +## Contributing |
142 | 146 |
|
143 | | -The problem is that due to the nature of how dependencies are installed in Lerna projects, the aliases in the example project's `package.json` might not point to the right place, as those dependencies might have been installed in the root of your Lerna project. |
| 147 | +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. |
144 | 148 |
|
145 | | -Change the `alias` to point to where those packages are actually installed. This depends on the directory structure of your Lerna project, so the actual path might be different from the diff below. |
| 149 | +Please make sure to update tests as appropriate. |
146 | 150 |
|
147 | | -```diff |
148 | | - "alias": { |
149 | | -- "react": "../node_modules/react", |
150 | | -- "react-dom": "../node_modules/react-dom" |
151 | | -+ "react": "../../../node_modules/react", |
152 | | -+ "react-dom": "../../../node_modules/react-dom" |
153 | | - }, |
154 | | -``` |
| 151 | +## License |
155 | 152 |
|
156 | | -An alternative to fixing this problem would be to remove aliases altogether and define the dependencies referenced as aliases as dev dependencies instead. [However, that might cause other problems.](https://github.com/palmerhq/tsdx/issues/64) |
| 153 | +[MIT](https://choosealicense.com/licenses/mit/) |
0 commit comments