From c89d18fd681856487ec14b19a7ffde52534c4a3f Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Tue, 27 Apr 2021 01:42:52 -0700 Subject: [PATCH] Introduce DataList Summary: Introduce the DataList component. Not feature complete yet, but core functionality is present so that people can use it during the convertathon. It is used to implement the route list in the network mock dialog Reviewed By: priteshrnandgaonkar Differential Revision: D27046716 fbshipit-source-id: a247ce7032b350b31bf55962ca4268e30f43471a --- .../flipper-plugin/src/__tests__/api.node.tsx | 1 + desktop/flipper-plugin/src/index.ts | 1 + .../flipper-plugin/src/state/DataSource.tsx | 5 +- desktop/flipper-plugin/src/ui/DataList.tsx | 152 ++++++++++++++++++ desktop/flipper-plugin/src/ui/Layout.tsx | 5 +- docs/extending/flipper-plugin.mdx | 13 ++ 6 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 desktop/flipper-plugin/src/ui/DataList.tsx diff --git a/desktop/flipper-plugin/src/__tests__/api.node.tsx b/desktop/flipper-plugin/src/__tests__/api.node.tsx index db7958e63..cab2fc4bf 100644 --- a/desktop/flipper-plugin/src/__tests__/api.node.tsx +++ b/desktop/flipper-plugin/src/__tests__/api.node.tsx @@ -31,6 +31,7 @@ test('Correct top level API exposed', () => { "DataDescription", "DataFormatter", "DataInspector", + "DataList", "DataSource", "DataTable", "DetailSidebar", diff --git a/desktop/flipper-plugin/src/index.ts b/desktop/flipper-plugin/src/index.ts index 7c1e1c6df..befb208c7 100644 --- a/desktop/flipper-plugin/src/index.ts +++ b/desktop/flipper-plugin/src/index.ts @@ -84,6 +84,7 @@ export {createDataSource, DataSource} from './state/DataSource'; export {DataTable, DataTableColumn} from './ui/data-table/DataTable'; export {DataTableManager} from './ui/data-table/DataTableManager'; +export {DataList} from './ui/DataList'; export { Interactive as _Interactive, diff --git a/desktop/flipper-plugin/src/state/DataSource.tsx b/desktop/flipper-plugin/src/state/DataSource.tsx index 80db9d2ac..e69ee570a 100644 --- a/desktop/flipper-plugin/src/state/DataSource.tsx +++ b/desktop/flipper-plugin/src/state/DataSource.tsx @@ -94,7 +94,10 @@ export class DataSource< private nextId = 0; private _records: Entry[] = []; private _recordsById: Map = new Map(); - private keyAttribute: undefined | keyof T; + /** + * @readonly + */ + public keyAttribute: undefined | keyof T; private idToIndex: Map = new Map(); // if we shift the window, we increase shiftOffset to correct idToIndex results, rather than remapping all values diff --git a/desktop/flipper-plugin/src/ui/DataList.tsx b/desktop/flipper-plugin/src/ui/DataList.tsx new file mode 100644 index 000000000..f6fc06764 --- /dev/null +++ b/desktop/flipper-plugin/src/ui/DataList.tsx @@ -0,0 +1,152 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import React, {useCallback, memo} from 'react'; +import {DataFormatter} from './DataFormatter'; +import {Layout} from './Layout'; +import {theme} from './theme'; +import {Typography} from 'antd'; + +const {Text} = Typography; + +interface Item { + id: string; + title: string; + description?: string; +} + +interface DataListProps { + /** + * Defines the styling of the component. By default shows a list, but alternatively the items can be displayed in a drop down + */ + type?: 'default' /* | 'compact' | 'dropdown' */; + /** + * By default the data list will take all available space and scroll if items aren't otherwise visible. + * By setting `scrollable={false}` the list will only take its natural size + */ + scrollable?: boolean; + /** + * The current selection + */ + value?: string /* | Atom*/; + /** + * Handler that is fired if selection is changed + */ + onSelect?(id: string, value: T): void; + className?: string; + style?: React.CSSProperties; + /** + * Items to display. Per item at least a title and unique id should be provided + */ + items: readonly Item[]; + /** + * Custom render function. By default the component will render the `title` in bold and description (if any) below it + */ + onRenderItem?: (item: T, selected: boolean) => React.ReactElement; +} + +export const DataList: React.FC> = function DataList< + T extends Item +>({ + // type, + scrollable, + value, + onSelect, + className, + style, + items, + onRenderItem, +}: DataListProps) { + const handleSelect = useCallback( + (key: string, item: T) => { + onSelect?.(key, item); + }, + [onSelect], + ); + + const renderedItems = items.map((item) => ( + + )); + + return scrollable ? ( + + {renderedItems} + + ) : ( + + {renderedItems} + + ); +}; + +DataList.defaultProps = { + type: 'default', + scrollable: false, + onRenderItem: defaultItemRenderer, +}; + +function defaultItemRenderer(item: Item, _selected: boolean) { + return ; +} + +const DataListItemWrapper = memo( + ({ + item, + onRenderItem, + onSelect, + selected, + }: { + item: Item; + onRenderItem: typeof defaultItemRenderer; + onSelect: (id: string, item: Item) => void; + selected: boolean; + }) => { + return ( + { + onSelect(item.id, item); + }}> + {onRenderItem(item, selected)} + + ); + }, +); + +const DataListItem = memo( + ({title, description}: {title: string; description?: string}) => { + return ( + <> + {DataFormatter.format(title)} + {description != null && ( + {DataFormatter.format(description)} + )} + + ); + }, +); diff --git a/desktop/flipper-plugin/src/ui/Layout.tsx b/desktop/flipper-plugin/src/ui/Layout.tsx index 0659d3e2f..021c5611b 100644 --- a/desktop/flipper-plugin/src/ui/Layout.tsx +++ b/desktop/flipper-plugin/src/ui/Layout.tsx @@ -88,9 +88,10 @@ const Container = styled.div( }), ); -const Horizontal = styled(Container)({ +const Horizontal = styled(Container)<{wrap?: boolean}>(({wrap}) => ({ flexDirection: 'row', -}); + flexWrap: wrap ? 'wrap' : undefined, +})); const ScrollParent = styled.div<{axis?: ScrollAxis}>(({axis}) => ({ flex: 1, diff --git a/docs/extending/flipper-plugin.mdx b/docs/extending/flipper-plugin.mdx index 228bb2f89..af97d83fb 100644 --- a/docs/extending/flipper-plugin.mdx +++ b/docs/extending/flipper-plugin.mdx @@ -809,6 +809,19 @@ See `View > Flipper Style Guide` inside the Flipper application for more details Coming soon. +### DataList + +The DataList can be used to display a set of items efficiently, and where a single item can be selected. + +Properties: + +* `items`: Items to display. Per item at least a title and unique id should be provided. +* `value`: The current selection +* `onSelect` +* `onRenderItem`: A custom render function. By default the component will render the `title` in bold and description (if any) below it. +* `type`: `default` or `dropdown. Defines the styling of the component. By default shows a list, but alternatively the items can be displayed in a drop down +* `scrollable`: By default the data list will take all available space and scroll if items aren't otherwise visible. By setting `scrollable={false}` the list will only take its natural size + ### NUX An element that can be used to provide a New User eXperience: Hints that give a one time introduction to new features to the current user.