Update to pure Sandy and update custom docs

Summary: Per title

Reviewed By: priteshrnandgaonkar

Differential Revision: D28991625

fbshipit-source-id: cab9cf59d1d053e2f8a47c588cb05abc44a527cc
This commit is contained in:
Michel Weststrate
2021-06-09 07:25:19 -07:00
committed by Facebook GitHub Bot
parent a0c872dd38
commit d2095d5937
5 changed files with 11 additions and 33 deletions

View File

@@ -5,7 +5,7 @@
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"main": "dist/bundle.js", "main": "dist/bundle.js",
"flipperBundlerEntry": "src/index_table.tsx", "flipperBundlerEntry": "src/index_custom.tsx",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
"flipper-plugin" "flipper-plugin"

View File

@@ -7,27 +7,6 @@
* @format * @format
*/ */
// eslint-disable-next-line
import {act} from '@testing-library/react';
{
// These mocks are needed because seammammals still uses Flipper in its UI implementation,
// so we need to mock some things
const origRequestIdleCallback = window.requestIdleCallback;
const origCancelIdleCallback = window.cancelIdleCallback;
// @ts-ignore
window.requestIdleCallback = (fn: () => void) => {
// the synchronous implementation forces DataInspector to render in sync
act(fn);
};
// @ts-ignore
window.cancelIdleCallback = clearImmediate;
afterAll(() => {
window.requestIdleCallback = origRequestIdleCallback;
window.cancelIdleCallback = origCancelIdleCallback;
});
}
import {TestUtils} from 'flipper-plugin'; import {TestUtils} from 'flipper-plugin';
import * as MammalsPlugin from '../index_custom'; import * as MammalsPlugin from '../index_custom';

View File

@@ -17,8 +17,9 @@ import {
useValue, useValue,
theme, theme,
styled, styled,
DataInspector,
DetailSidebar,
} from 'flipper-plugin'; } from 'flipper-plugin';
import {ManagedDataInspector, DetailSidebar} from 'flipper';
type Row = { type Row = {
id: number; id: number;
@@ -47,10 +48,9 @@ export function plugin(client: PluginClient<Events, {}>) {
handler: async () => { handler: async () => {
const selection = selectedID.get(); const selection = selectedID.get();
if (selection) { if (selection) {
const url = await client.createPaste( await client.createPaste(
JSON.stringify(rows.get()[selection], null, 2), JSON.stringify(rows.get()[selection], null, 2),
); );
alert(url); // TODO: use notifications T69990351
} }
}, },
}, },
@@ -105,7 +105,7 @@ function renderSidebar(row: Row) {
return ( return (
<Layout.Container gap pad> <Layout.Container gap pad>
<Typography.Title level={4}>Extras</Typography.Title> <Typography.Title level={4}>Extras</Typography.Title>
<ManagedDataInspector data={row} expandRoot /> <DataInspector data={row} expandRoot />
</Layout.Container> </Layout.Container>
); );
} }

View File

@@ -11,16 +11,15 @@ Displaying your data in a table might work for many use-cases. However, dependin
## Replacing the table ## Replacing the table
For our sea mammals app, we might not only want to see them listed as image URLs in a table but render the actual images in nice little cards. When selecting one of the cards we still want to display all details in the sidebar. For our sea mammals app, we might not only want to see them listed as image URLs in a table but render the actual images in nice little cards. When selecting one of the cards we still want to display all details in the sidebar.
<img alt="Custom cards UI for our sea mammals plugin" src={useBaseUrl("img/js-custom.png")} /> <img alt="Custom cards UI for our sea mammals plugin" src={useBaseUrl("img/js-custom.png")} />
Currently, the default export in our `index.tsx` is from `createTablePlugin`. Currently, the default export in our `index.tsx` is from `createTablePlugin`.
Now we are going to replace this with a custom React component by using the more flexible APIs exposed by `flipper-plugin` . Now we are going to replace this with a custom React component by using the more flexible APIs exposed by `flipper-plugin` .
So first let's add `flipper-plugin` as dependency: `yarn add --peer flipper-plugin antd && yarn add --dev flipper-plugin antd`.
After that, we replace our `createTablePlugin` with a `plugin` definition, and a `Component` definition which is used for rendering. After that, we replace our `createTablePlugin` with a `plugin` definition, and a `Component` definition which is used for rendering.
Separating those two concepts helps with testing and maintaining state when the user switches plugins. Separating those two concepts helps with testing and maintaining state when the user switches plugins.
```tsx ```tsx
import React from 'react'; import React from 'react';
import {PluginClient, createState} from 'flipper-plugin'; import {PluginClient, createState} from 'flipper-plugin';
@@ -90,6 +89,7 @@ In this case, we return the state atoms `rows` and `selectedID`, and expose the
Since the `plugin` function will execute only once during the entire life-cycle of the plugin, we can use local variables in the function body to preserve state. Since the `plugin` function will execute only once during the entire life-cycle of the plugin, we can use local variables in the function body to preserve state.
In our example, we create two pieces of state, the set of rows available, `rows`, and the current selection: `selectionID`. See `(5)`. In our example, we create two pieces of state, the set of rows available, `rows`, and the current selection: `selectionID`. See `(5)`.
For larger data collections, we strongly recommend to leverage the better optimized [`createDataSource`](../extending/flipper-plugin#createdatasource), but in this simple example `createState` will suffice for the small data set.
It is possible to store state directly in `let` declarations, but `createState` creates a storage container that gives us a few advantages. It is possible to store state directly in `let` declarations, but `createState` creates a storage container that gives us a few advantages.
Most importantly, state created using `createState` can be subscribed to by our UI components using the `useValue` hook. Most importantly, state created using `createState` can be subscribed to by our UI components using the `useValue` hook.
@@ -176,8 +176,6 @@ The assertions are provided by [Jest](https://jestjs.io/), and `toMatchInlineSna
## Building a User Interface for the plugin ## Building a User Interface for the plugin
_Note: For now, the plugin implementation as shown here uses the old Flipper component library `flipper`, expect nicer components in the future as part of `flipper-plugin`._
So far, in `index.tsx`, our `Component` didn't do anything useful yet. Time to build some nice UI. So far, in `index.tsx`, our `Component` didn't do anything useful yet. Time to build some nice UI.
Flipper leverages Ant design, so any [official Ant component](https://ant.design/components/overview/) can be used in Flipper plugins. Flipper leverages Ant design, so any [official Ant component](https://ant.design/components/overview/) can be used in Flipper plugins.
@@ -195,8 +193,9 @@ import {
useValue, useValue,
theme, theme,
styled, styled,
DataInspector,
DetailSidebar
} from 'flipper-plugin'; } from 'flipper-plugin';
import {ManagedDataInspector, DetailSidebar} from 'flipper';
// (1) // (1)
export function Component() { export function Component() {
@@ -234,7 +233,7 @@ function renderSidebar(row: Row) {
return ( return (
<Layout.Container gap pad> <Layout.Container gap pad>
<Typography.Title level={4}>Extras</Typography.Title> <Typography.Title level={4}>Extras</Typography.Title>
<ManagedDataInspector data={row} expandRoot={true} /> <DataInspector data={row} expandRoot={true} />
</Layout.Container> </Layout.Container>
); );
} }
@@ -258,7 +257,7 @@ So it is not necessary to grab all the data at the root and pass it down using p
Using `useValue` as deep in the component tree as possible will benefit performance. Using `useValue` as deep in the component tree as possible will benefit performance.
Finally (`(4)`) we render the data we have. The details have been left out here, as from here it is just idiomatic React code. Finally (`(4)`) we render the data we have. The details have been left out here, as from here it is just idiomatic React code.
The source of the other `MammalCard` component can be found [here](https://github.com/facebook/flipper/blob/master/desktop/plugins/public/seamammals/src/index.tsx#L113-L165). The source of the other `MammalCard` component can be found [here](https://github.com/facebook/flipper/blob/master/desktop/plugins/public/seamammals/src/index_custom.tsx#L118-L132).
Tip: it is recommended to keep components as much as possible outside the entry file, as components defined outside the index.tsx file will benefit from fast refresh. Tip: it is recommended to keep components as much as possible outside the entry file, as components defined outside the index.tsx file will benefit from fast refresh.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 729 KiB