diff --git a/desktop/app/src/fb-stubs/IDEFileResolver.tsx b/desktop/app/src/fb-stubs/IDEFileResolver.tsx index bda4cd339..1c5b3c8dc 100644 --- a/desktop/app/src/fb-stubs/IDEFileResolver.tsx +++ b/desktop/app/src/fb-stubs/IDEFileResolver.tsx @@ -7,10 +7,8 @@ * @format */ -import { - ElementFramework, - Element, -} from '../ui/components/elements-inspector/ElementsInspector'; +import {ElementFramework} from '../ui/components/elements-inspector/ElementFramework'; +import {ElementsInspectorElement} from 'flipper-plugin'; export enum IDEType { 'DIFFUSION', @@ -60,13 +58,15 @@ export abstract class IDEFileResolver { } static isElementFromFramework( - _node: Element, + _node: ElementsInspectorElement, _framework: ElementFramework, ): boolean { throw new Error('Method not implemented.'); } - static isElementFromSupportedFramework(_node: Element): boolean { + static isElementFromSupportedFramework( + _node: ElementsInspectorElement, + ): boolean { throw new Error('Method not implemented.'); } } diff --git a/desktop/app/src/index.tsx b/desktop/app/src/index.tsx index 913649221..0493b82a0 100644 --- a/desktop/app/src/index.tsx +++ b/desktop/app/src/index.tsx @@ -173,20 +173,17 @@ export { } from './ui/components/searchable/SearchableTable'; export {default as SearchableTable_immutable} from './ui/components/searchable/SearchableTable_immutable'; export { - ElementID, - ElementData, - ElementFramework, - ElementAttribute, - Element, - ElementSearchResultSet, + ElementsInspector, + ElementsInspectorElement as Element, + // TODO: clean up or create namespace ElementsInspectorProps, -} from './ui/components/elements-inspector/ElementsInspector'; -export { - Elements, - ElementsConstants, -} from './ui/components/elements-inspector/elements'; -export {ContextMenuExtension} from './ui/components/elements-inspector/elements'; -export {default as ElementsInspector} from './ui/components/elements-inspector/ElementsInspector'; + ElementExtraInfo, + ElementAttribute, + ElementData, + ElementSearchResultSet, + ElementID, +} from 'flipper-plugin'; +export {ElementFramework} from './ui/components/elements-inspector/ElementFramework'; export {InspectorSidebar} from './ui/components/elements-inspector/sidebar'; export {default as Sheet} from './ui/components/Sheet'; export {default as FileSelector} from './ui/components/FileSelector'; diff --git a/desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx b/desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx new file mode 100644 index 000000000..0f282382f --- /dev/null +++ b/desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx @@ -0,0 +1,13 @@ +/** + * 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 + */ + +export enum ElementFramework { + 'LITHO', + 'CK', +} diff --git a/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx b/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx index 02fd4b399..95bbec386 100644 --- a/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx +++ b/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx @@ -9,18 +9,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import {Element} from './ElementsInspector'; +import {ElementsInspectorElement} from 'flipper-plugin'; import styled from '@emotion/styled'; export function VisualizerPortal(props: { container: HTMLElement; highlightedElement: string | null; - elements: {[key: string]: Element}; + elements: {[key: string]: ElementsInspectorElement}; screenshotURL: string; screenDimensions: {width: number; height: number}; }) { props.container.style.margin = '0'; - const element: Element | null | '' = + const element: ElementsInspectorElement | null | '' = props.highlightedElement && props.elements[props.highlightedElement]; const position = diff --git a/desktop/app/src/ui/components/elements-inspector/sidebar.tsx b/desktop/app/src/ui/components/elements-inspector/sidebar.tsx index cd12b1f4d..04bf3eca9 100644 --- a/desktop/app/src/ui/components/elements-inspector/sidebar.tsx +++ b/desktop/app/src/ui/components/elements-inspector/sidebar.tsx @@ -7,7 +7,7 @@ * @format */ -import {Element} from './ElementsInspector'; +import {ElementsInspectorElement} from 'flipper-plugin'; import {PluginClient} from '../../../plugin'; import Client from '../../../Client'; import {Logger} from '../../../fb-interfaces/Logger'; @@ -76,7 +76,7 @@ class InspectorSidebarSection extends Component { } type Props = { - element: Element | undefined | null; + element: ElementsInspectorElement | undefined | null; tooltips?: Object; onValueChanged: OnValueChanged | undefined | null; client: PluginClient; diff --git a/desktop/app/src/ui/index.tsx b/desktop/app/src/ui/index.tsx index 48e4f5e46..69a363b3f 100644 --- a/desktop/app/src/ui/index.tsx +++ b/desktop/app/src/ui/index.tsx @@ -141,17 +141,6 @@ export { export {default as SearchableTable_immutable} from './components/searchable/SearchableTable_immutable'; export {SearchableProps} from './components/searchable/Searchable'; -export { - ElementID, - ElementData, - ElementAttribute, - Element, - ElementSearchResultSet, - ElementsInspectorProps, -} from './components/elements-inspector/ElementsInspector'; -export {Elements} from './components/elements-inspector/elements'; -export {ContextMenuExtension} from './components/elements-inspector/elements'; -export {default as ElementsInspector} from './components/elements-inspector/ElementsInspector'; export {InspectorSidebar} from './components/elements-inspector/sidebar'; export {VisualizerPortal} from './components/elements-inspector/Visualizer'; diff --git a/desktop/flipper-plugin/src/__tests__/api.node.tsx b/desktop/flipper-plugin/src/__tests__/api.node.tsx index f99f0fa32..76f1d265e 100644 --- a/desktop/flipper-plugin/src/__tests__/api.node.tsx +++ b/desktop/flipper-plugin/src/__tests__/api.node.tsx @@ -34,6 +34,7 @@ test('Correct top level API exposed', () => { "DataSource", "DataTable", "DetailSidebar", + "ElementsInspector", "Layout", "MarkerTimeline", "NUX", @@ -72,6 +73,13 @@ test('Correct top level API exposed', () => { "DevicePluginClient", "DeviceType", "Draft", + "ElementAttribute", + "ElementData", + "ElementExtraInfo", + "ElementID", + "ElementSearchResultSet", + "ElementsInspectorElement", + "ElementsInspectorProps", "FlipperLib", "HighlightManager", "Idler", diff --git a/desktop/flipper-plugin/src/index.ts b/desktop/flipper-plugin/src/index.ts index 088b902d2..72d960219 100644 --- a/desktop/flipper-plugin/src/index.ts +++ b/desktop/flipper-plugin/src/index.ts @@ -102,6 +102,17 @@ export { export {MarkerTimeline} from './ui/MarkerTimeline'; export {ManagedDataInspector as DataInspector} from './ui/data-inspector/ManagedDataInspector'; +export { + ElementsInspector, + Element as ElementsInspectorElement, + // TODO: clean up or create namespace + ElementsInspectorProps, + ElementExtraInfo, + ElementAttribute, + ElementData, + ElementSearchResultSet, + ElementID, +} from './ui/elements-inspector/ElementsInspector'; export {useMemoize} from './utils/useMemoize'; // It's not ideal that this exists in flipper-plugin sources directly, diff --git a/desktop/flipper-plugin/src/ui/Layout.tsx b/desktop/flipper-plugin/src/ui/Layout.tsx index be1838de5..380f1bbe8 100644 --- a/desktop/flipper-plugin/src/ui/Layout.tsx +++ b/desktop/flipper-plugin/src/ui/Layout.tsx @@ -7,7 +7,7 @@ * @format */ -import React, {CSSProperties} from 'react'; +import React, {CSSProperties, forwardRef} from 'react'; import styled from '@emotion/styled'; import { normalizePadding, @@ -110,28 +110,33 @@ const ScrollChild = styled(Container)<{axis?: ScrollAxis}>(({axis}) => ({ type ScrollAxis = 'x' | 'y' | 'both'; -const ScrollContainer = ({ - children, - horizontal, - vertical, - padv, - padh, - pad, - ...rest -}: React.HTMLAttributes & { - horizontal?: boolean; - vertical?: boolean; -} & PaddingProps) => { - const axis = - horizontal && !vertical ? 'x' : !horizontal && vertical ? 'y' : 'both'; - return ( - - - {children} - - - ) as any; -}; +const ScrollContainer = forwardRef( + ( + { + children, + horizontal, + vertical, + padv, + padh, + pad, + ...rest + }: React.HTMLAttributes & { + horizontal?: boolean; + vertical?: boolean; + } & PaddingProps, + ref: React.ForwardedRef, + ) => { + const axis = + horizontal && !vertical ? 'x' : !horizontal && vertical ? 'y' : 'both'; + return ( + + + {children} + + + ) as any; + }, +); type SplitLayoutProps = { /** diff --git a/desktop/app/src/ui/components/elements-inspector/ElementsInspector.tsx b/desktop/flipper-plugin/src/ui/elements-inspector/ElementsInspector.tsx similarity index 91% rename from desktop/app/src/ui/components/elements-inspector/ElementsInspector.tsx rename to desktop/flipper-plugin/src/ui/elements-inspector/ElementsInspector.tsx index 5251c0d58..591751477 100644 --- a/desktop/app/src/ui/components/elements-inspector/ElementsInspector.tsx +++ b/desktop/flipper-plugin/src/ui/elements-inspector/ElementsInspector.tsx @@ -8,8 +8,7 @@ */ import {Component} from 'react'; -import {Elements, DecorateRow} from './elements'; -import {ContextMenuExtension} from '../../../ui'; +import {Elements, DecorateRow, ContextMenuExtension} from './elements'; import React from 'react'; export type ElementID = string; @@ -32,11 +31,6 @@ export type ElementData = { }; }; -export enum ElementFramework { - 'LITHO', - 'CK', -} - export type ElementAttribute = { name: string; value: string; @@ -80,7 +74,7 @@ export type ElementsInspectorProps = { decorateRow?: DecorateRow; }; -export default class ElementsInspector extends Component { +export class ElementsInspector extends Component { static defaultProps = { alternateRowColor: true, }; diff --git a/desktop/app/src/ui/components/elements-inspector/elements.tsx b/desktop/flipper-plugin/src/ui/elements-inspector/elements.tsx similarity index 85% rename from desktop/app/src/ui/components/elements-inspector/elements.tsx rename to desktop/flipper-plugin/src/ui/elements-inspector/elements.tsx index 37b140f58..21fcf20a1 100644 --- a/desktop/app/src/ui/components/elements-inspector/elements.tsx +++ b/desktop/flipper-plugin/src/ui/elements-inspector/elements.tsx @@ -7,17 +7,17 @@ * @format */ +import {Dropdown, Menu, Typography} from 'antd'; import {ElementID, Element, ElementSearchResultSet} from './ElementsInspector'; -import ContextMenu from '../ContextMenu'; import {PureComponent, ReactElement} from 'react'; -import FlexRow from '../FlexRow'; -import Glyph from '../Glyph'; -import {colors} from '../colors'; -import Text from '../Text'; import styled from '@emotion/styled'; -import {clipboard, MenuItemConstructorOptions} from 'electron'; import React, {MouseEvent, KeyboardEvent} from 'react'; -import {Scrollable} from '../..'; +import {theme} from '../theme'; +import {Layout} from '../Layout'; +import {tryGetFlipperLibImplementation} from 'flipper-plugin/src/plugin/FlipperLib'; +import {DownOutlined, RightOutlined} from '@ant-design/icons'; + +const {Text} = Typography; export const ElementsConstants = { rowHeight: 23, @@ -30,13 +30,13 @@ const backgroundColor = (props: { even: boolean; }) => { if (props.selected) { - return colors.macOSTitleBarIconSelected; + return '#4d84f5'; } else if (props.isQueryMatch) { - return colors.purpleLight; + return '#4d84f5'; } else if (props.focused) { return '#00CF52'; } else if (props.even) { - return colors.light02; + return '#f6f7f9'; } else { return ''; } @@ -44,7 +44,7 @@ const backgroundColor = (props: { const backgroundColorHover = (props: {selected: boolean; focused: boolean}) => { if (props.selected) { - return colors.macOSTitleBarIconSelected; + return '#4d84f5'; } else if (props.focused) { return '#00CF52'; } else { @@ -52,11 +52,11 @@ const backgroundColorHover = (props: {selected: boolean; focused: boolean}) => { } }; -const ElementsRowContainer = styled(ContextMenu)((props) => ({ +const ElementsRowContainer = styled(Layout.Horizontal)((props) => ({ flexDirection: 'row', alignItems: 'center', backgroundColor: backgroundColor(props), - color: props.selected || props.focused ? colors.white : colors.grapeDark3, + color: props.selected || props.focused ? theme.backgroundDefault : '#58409b', flexShrink: 0, flexWrap: 'nowrap', height: ElementsConstants.rowHeight, @@ -65,7 +65,10 @@ const ElementsRowContainer = styled(ContextMenu)((props) => ({ position: 'relative', '& *': { - color: props.selected || props.focused ? `${colors.white} !important` : '', + color: + props.selected || props.focused + ? `${theme.backgroundDefault} !important` + : '', }, '&:hover': { @@ -74,7 +77,7 @@ const ElementsRowContainer = styled(ContextMenu)((props) => ({ })); ElementsRowContainer.displayName = 'Elements:ElementsRowContainer'; -const ElementsRowDecoration = styled(FlexRow)({ +const ElementsRowDecoration = styled(Layout.Horizontal)({ flexShrink: 0, justifyContent: 'flex-end', alignItems: 'center', @@ -86,7 +89,7 @@ const ElementsRowDecoration = styled(FlexRow)({ ElementsRowDecoration.displayName = 'Elements:ElementsRowDecoration'; const ElementsLine = styled.div<{childrenCount: number}>((props) => ({ - backgroundColor: colors.light20, + backgroundColor: '#bec2c9', height: props.childrenCount * ElementsConstants.rowHeight - 4, position: 'absolute', right: 3, @@ -109,11 +112,13 @@ const NoShrinkText = styled(Text)({ flexWrap: 'nowrap', overflow: 'hidden', fontWeight: 400, + font: theme.monospace.fontFamily, + fontSize: theme.monospace.fontSize, }); NoShrinkText.displayName = 'Elements:NoShrinkText'; const ElementsRowAttributeContainer = styled(NoShrinkText)({ - color: colors.dark80, + color: '#333333', fontWeight: 300, marginLeft: 5, }); @@ -121,12 +126,12 @@ ElementsRowAttributeContainer.displayName = 'Elements:ElementsRowAttributeContainer'; const ElementsRowAttributeKey = styled.span({ - color: colors.tomato, + color: '#fb724b', }); ElementsRowAttributeKey.displayName = 'Elements:ElementsRowAttributeKey'; const ElementsRowAttributeValue = styled.span({ - color: colors.slateDark3, + color: '#688694', }); ElementsRowAttributeValue.displayName = 'Elements:ElementsRowAttributeValue'; @@ -137,8 +142,8 @@ class PartialHighlight extends PureComponent<{ content: string; }> { static HighlightedText = styled.span<{selected: boolean}>((props) => ({ - backgroundColor: colors.lemon, - color: props.selected ? `${colors.grapeDark3} !important` : 'auto', + backgroundColor: '#fcd872', + color: props.selected ? `${'#58409b'} !important` : 'auto', })); render() { @@ -180,7 +185,7 @@ class ElementsRowAttribute extends PureComponent<{ render() { const {name, value, matchingSearchQuery, selected} = this.props; return ( - + {name}= { this.state = {hovered: false}; } - getContextMenu = (): Array => { + getContextMenu = () => { const {props} = this; - let items: Array = [ - { - type: 'separator', - }, + let items = [ { label: 'Copy', click: () => { - clipboard.writeText(props.onCopyExpandedTree(props.element, 0)); + tryGetFlipperLibImplementation()?.writeTextToClipboard( + props.onCopyExpandedTree(props.element, 0), + ); }, }, { label: 'Copy expanded child elements', click: () => - clipboard.writeText(props.onCopyExpandedTree(props.element, 255)), + tryGetFlipperLibImplementation()?.writeTextToClipboard( + props.onCopyExpandedTree(props.element, 255), + ), }, { label: props.element.expanded ? 'Collapse' : 'Expand', @@ -274,7 +280,7 @@ class ElementsRow extends PureComponent { return { label: `Copy ${o.name}`, click: () => { - clipboard.writeText(o.value); + tryGetFlipperLibImplementation()?.writeTextToClipboard(o.value); }, }; }), @@ -287,7 +293,15 @@ class ElementsRow extends PureComponent { }); } - return items; + return ( + + {items.map(({label, click}) => ( + + {label} + + ))} + + ); }; onClick = () => { @@ -330,12 +344,15 @@ class ElementsRow extends PureComponent { let arrow; if (hasChildren) { arrow = ( - - + + {element.expanded ? : } ); } @@ -377,35 +394,38 @@ class ElementsRow extends PureComponent { } return ( - - - {line} - {arrow} - - - {decoration} - - - {attributes} - + overlay={this.getContextMenu} + trigger={['contextMenu']}> + + + {line} + {arrow} + + + {decoration} + + + {attributes} + + ); } } @@ -419,7 +439,7 @@ function containsKeyInSearchResults( const ElementsContainer = styled('div')({ display: 'table', - backgroundColor: colors.white, + backgroundColor: theme.backgroundDefault, minHeight: '100%', minWidth: '100%', }); @@ -568,7 +588,9 @@ export class Elements extends PureComponent { ) { e.stopPropagation(); e.preventDefault(); - clipboard.writeText(selectedElement.name); + tryGetFlipperLibImplementation()?.writeTextToClipboard( + selectedElement.name, + ); return; } @@ -735,11 +757,11 @@ export class Elements extends PureComponent { render() { return ( - + {this.state.flatElements.map(this.buildRow)} - + ); } } diff --git a/desktop/plugins/public/layout/MultipleSelectionSection.tsx b/desktop/plugins/public/layout/MultipleSelectionSection.tsx index c37bba360..d767f7484 100644 --- a/desktop/plugins/public/layout/MultipleSelectionSection.tsx +++ b/desktop/plugins/public/layout/MultipleSelectionSection.tsx @@ -11,7 +11,6 @@ import { FlexColumn, FlexBox, Element, - ElementsConstants, ElementID, ElementsInspector, Glyph, @@ -21,7 +20,7 @@ import { import React, {memo, useState} from 'react'; const MultipleSelectorSectionContainer = styled(FlexColumn)({ - maxHeight: 3 * ElementsConstants.rowHeight + 24, + maxHeight: 100, }); const MultipleSelectorSectionTitle = styled(FlexBox)({ diff --git a/docs/extending/flipper-plugin.mdx b/docs/extending/flipper-plugin.mdx index c8cd3e688..95bbb66d9 100644 --- a/docs/extending/flipper-plugin.mdx +++ b/docs/extending/flipper-plugin.mdx @@ -784,6 +784,14 @@ See `View > Flipper Style Guide` inside the Flipper application for more details ### DataInspector ### DataDescription ### MarkerTimeline +### ElementsInspector +### ElementAttribute +### ElementData +### ElementExtraInfo +### ElementID +### ElementSearchResultSet +### ElementsInspectorElement +### ElementsInspectorProps Coming soon.