Files
flipper/desktop/plugins/public/seamammals/src/index_custom.tsx
Andres Suarez 79023ee190 Update copyright headers from Facebook to Meta
Reviewed By: bhamodi

Differential Revision: D33331422

fbshipit-source-id: 016e8dcc0c0c7f1fc353a348b54fda0d5e2ddc01
2021-12-27 14:31:45 -08:00

138 lines
2.9 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and 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, {memo} from 'react';
import {Typography, Card} from 'antd';
import {
Layout,
PluginClient,
usePlugin,
createState,
useValue,
theme,
styled,
DataInspector,
DetailSidebar,
} from 'flipper-plugin';
type Row = {
id: number;
title: string;
url: string;
};
type Events = {
newRow: Row;
};
export function plugin(client: PluginClient<Events, {}>) {
const rows = createState<Record<string, Row>>({}, {persist: 'rows'});
const selectedID = createState<string | null>(null, {persist: 'selection'});
client.addMenuEntry(
{
label: 'Reset Selection',
handler: () => {
selectedID.set(null);
},
},
{
action: 'createPaste',
handler: async () => {
const selection = selectedID.get();
if (selection) {
await client.createPaste(
JSON.stringify(rows.get()[selection], null, 2),
);
}
},
},
);
client.onMessage('newRow', (row) => {
rows.update((draft) => {
draft[row.id] = row;
});
});
function setSelection(id: number) {
selectedID.set('' + id);
}
return {
rows,
selectedID,
setSelection,
};
}
export function Component() {
const instance = usePlugin(plugin);
const rows = useValue(instance.rows);
const selectedID = useValue(instance.selectedID);
return (
<>
<Layout.ScrollContainer
vertical
style={{background: theme.backgroundWash}}>
<Layout.Horizontal gap pad style={{flexWrap: 'wrap'}}>
{Object.entries(rows).map(([id, row]) => (
<MammalCard
row={row}
onSelect={instance.setSelection}
selected={id === selectedID}
key={id}
/>
))}
</Layout.Horizontal>
</Layout.ScrollContainer>
<DetailSidebar>
{selectedID && renderSidebar(rows[selectedID])}
</DetailSidebar>
</>
);
}
function renderSidebar(row: Row) {
return (
<Layout.Container gap pad>
<Typography.Title level={4}>Extras</Typography.Title>
<DataInspector data={row} expandRoot />
</Layout.Container>
);
}
type CardProps = {
onSelect: (id: number) => void;
selected: boolean;
row: Row;
};
const MammalCard = memo(({row, selected, onSelect}: CardProps) => {
return (
<Card
hoverable
data-testid={row.title}
onClick={() => onSelect(row.id)}
title={row.title}
style={{
width: 150,
borderColor: selected ? theme.primaryColor : undefined,
}}>
<Image style={{backgroundImage: `url(${row.url || ''})`}} />
</Card>
);
});
const Image = styled.div({
backgroundSize: 'cover',
width: '100%',
paddingTop: '100%',
});