flipper-plugin
Version:
Flipper Desktop plugin SDK and components
176 lines • 8 kB
JavaScript
"use strict";
/**
* 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
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MasterDetail = void 0;
const React = __importStar(require("react"));
const react_1 = require("react");
const DataInspector_1 = require("./data-inspector/DataInspector");
const DataTable_1 = require("./data-table/DataTable");
const DetailSidebar_1 = require("./DetailSidebar");
const Layout_1 = require("./Layout");
const Panel_1 = require("./Panel");
const icons_1 = require("@ant-design/icons");
const antd_1 = require("antd");
const PluginContext_1 = require("../plugin/PluginContext");
const useAssertStableRef_1 = require("../utils/useAssertStableRef");
const atom_1 = require("../state/atom");
function MasterDetail({ dataSource, records, sidebarComponent, sidebarPosition, sidebarSize, onSelect, extraActions, enableMenuEntries, enableClear, isPaused, selection, onClear, ...tableProps }) {
(0, useAssertStableRef_1.useAssertStableRef)(isPaused, 'isPaused');
(0, useAssertStableRef_1.useAssertStableRef)(selection, 'selection');
const pluginInstance = (0, PluginContext_1.usePluginInstance)();
const { client } = pluginInstance;
const connected = (0, atom_1.useValue)(pluginInstance.client.connected);
const selectionAtom =
// if no selection atom is provided, the component is uncontrolled
// and we maintain our own selection atom
// eslint-disable-next-line
selection ?? (0, react_1.useState)(() => (0, atom_1.createState)(undefined))[0];
const selectedRecord = (0, atom_1.useValue)(selectionAtom);
// if a tableManagerRef is provided, we piggy back on that same ref
// eslint-disable-next-line
const tableManagerRef = tableProps.tableManagerRef ?? (0, react_1.createRef)();
const pausedState = (0, atom_1.useValue)(isPaused, false);
const sidebar = sidebarPosition !== 'none' && selectedRecord && sidebarComponent
? (0, react_1.createElement)(sidebarComponent, {
record: selectedRecord,
tableManagerRef,
})
: null;
const handleSelect = (0, react_1.useCallback)((record, records) => {
selectionAtom.set(record);
onSelect?.(record, records);
}, [selectionAtom, onSelect]);
const handleTogglePause = (0, react_1.useCallback)(() => {
isPaused?.set(!isPaused?.get());
}, [isPaused]);
const handleClear = (0, react_1.useCallback)(() => {
handleSelect(undefined, []);
if (dataSource) {
dataSource.clear();
onClear?.();
}
else {
if (!onClear) {
throw new Error("onClear must be set when using 'enableClear' and 'records'");
}
onClear();
}
}, [dataSource, onClear, handleSelect]);
const handleCreatePaste = (0, react_1.useCallback)(() => {
const selection = tableManagerRef.current?.getSelectedItems();
switch (selection?.length) {
case undefined:
case 0:
return;
case 1:
client.createPaste(JSON.stringify(selection[0], null, 2));
break;
default:
client.createPaste(JSON.stringify(selection, null, 2));
}
}, [client, tableManagerRef]);
const handleGoToBottom = (0, react_1.useCallback)(() => {
// TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const size = dataSource ? dataSource.view.size : records.length;
tableManagerRef?.current?.selectItem(size - 1);
}, [dataSource, records, tableManagerRef]);
(0, react_1.useEffect)(function setupMenuEntries() {
if (enableMenuEntries) {
if (enableClear) {
client.addMenuEntry({
action: 'clear',
handler: handleClear,
});
}
if (client.isFB) {
client.addMenuEntry({
action: 'createPaste',
handler: handleCreatePaste,
});
}
client.addMenuEntry({
action: 'goToBottom',
handler: handleGoToBottom,
});
}
}, [
client,
enableClear,
enableMenuEntries,
handleClear,
handleCreatePaste,
handleGoToBottom,
]);
const table = (React.createElement(DataTable_1.DataTable, { enableAutoScroll: true, ...tableProps, dataSource: dataSource,
// TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
records: records, tableManagerRef: tableManagerRef, onSelect: handleSelect, extraActions: React.createElement(React.Fragment, null,
connected && isPaused && (React.createElement(antd_1.Button, { title: `Click to ${pausedState ? 'resume' : 'pause'} the stream`, danger: pausedState, onClick: handleTogglePause }, pausedState ? React.createElement(icons_1.PlayCircleOutlined, null) : React.createElement(icons_1.PauseCircleOutlined, null))),
connected && enableClear && (React.createElement(antd_1.Button, { title: "Clear records", onClick: handleClear },
React.createElement(icons_1.DeleteOutlined, null))),
extraActions) }));
// TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
switch (sidebarPosition) {
case 'main':
return (React.createElement(Layout_1.Layout.Container, { grow: true },
table,
React.createElement(DetailSidebar_1.DetailSidebar, { width: sidebarSize }, sidebar)));
case 'right':
return (React.createElement(Layout_1.Layout.Right, { resizable: true, width: sidebarSize },
table,
sidebar));
case 'bottom':
return (React.createElement(Layout_1.Layout.Bottom, { resizable: true, height: sidebarSize },
table,
sidebar));
case 'overlay':
return (React.createElement(Layout_1.Layout.Container, { grow: true, style: { position: 'relative' } },
table,
sidebar));
case 'none':
return table;
}
}
exports.MasterDetail = MasterDetail;
MasterDetail.defaultProps = {
sidebarPosition: 'main',
sidebarSize: 400,
sidebarComponent: DefaultRenderSidebar,
};
function DefaultRenderSidebar({ record }) {
return (React.createElement(Panel_1.Panel, { title: "Payload", collapsible: false, pad: true },
React.createElement(DataInspector_1.DataInspector, { data: record, expandRoot: true })));
}
//# sourceMappingURL=MasterDetail.js.map