diff --git a/src/index.js b/src/index.js index 8d89c29b3..f55d1959b 100644 --- a/src/index.js +++ b/src/index.js @@ -172,14 +172,14 @@ export { ElementAttribute, Element, ElementSearchResultSet, -} from './ui/components/elements-inspector/ElementsInspector.js'; -export {Elements} from './ui/components/elements-inspector/elements.js'; +} from './ui/components/elements-inspector/ElementsInspector.tsx'; +export {Elements} from './ui/components/elements-inspector/elements.tsx'; export { ContextMenuExtension, -} from './ui/components/elements-inspector/elements.js'; +} from './ui/components/elements-inspector/elements.tsx'; export { default as ElementsInspector, -} from './ui/components/elements-inspector/ElementsInspector.js'; -export {InspectorSidebar} from './ui/components/elements-inspector/sidebar.js'; +} from './ui/components/elements-inspector/ElementsInspector.tsx'; +export {InspectorSidebar} from './ui/components/elements-inspector/sidebar.tsx'; export {Console} from './ui/components/console.tsx'; export {default as Sheet} from './ui/components/Sheet.tsx'; diff --git a/src/ui/components/elements-inspector/ElementsInspector.js b/src/ui/components/elements-inspector/ElementsInspector.js deleted file mode 100644 index 4f4cda8d2..000000000 --- a/src/ui/components/elements-inspector/ElementsInspector.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright 2018-present Facebook. - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * @format - */ - -import {Component} from 'react'; -import FlexRow from '../FlexRow.tsx'; -import {Elements, type DecorateRow} from './elements.js'; -import type {ContextMenuExtension} from 'flipper'; - -export type ElementID = string; - -export type ElementSearchResultSet = {| - query: string, - matches: Set, -|}; - -export type ElementData = { - [name: ElementID]: { - [key: string]: - | string - | number - | boolean - | {| - __type__: string, - value: any, - |}, - }, -}; - -export type ElementAttribute = {| - name: string, - value: string, -|}; - -export type ElementExtraInfo = {| - linkedNode?: string, // id of linked node in opposite tree - expandWithParent?: boolean, -|}; - -export type Element = {| - id: ElementID, - name: string, - expanded: boolean, - children: Array, - attributes: Array, - data: ElementData, - decoration: string, - extraInfo: ElementExtraInfo, -|}; - -export default class ElementsInspector extends Component<{ - onElementExpanded: (key: ElementID, deep: boolean) => void, - onElementSelected: (key: ElementID) => void, - onElementHovered: ?(key: ?ElementID) => void, - onValueChanged: ?(path: Array, val: any) => void, - selected: ?ElementID, - focused?: ?ElementID, - searchResults?: ?ElementSearchResultSet, - root: ?ElementID, - elements: {[key: ElementID]: Element}, - useAppSidebar?: boolean, - alternateRowColor?: boolean, - contextMenuExtensions?: Array, - decorateRow?: DecorateRow, -}> { - static defaultProps = { - alternateRowColor: true, - }; - render() { - const { - selected, - focused, - elements, - root, - onElementExpanded, - onElementSelected, - onElementHovered, - searchResults, - alternateRowColor, - contextMenuExtensions, - decorateRow, - } = this.props; - - return ( - - ); - } -} diff --git a/src/ui/components/elements-inspector/ElementsInspector.tsx b/src/ui/components/elements-inspector/ElementsInspector.tsx new file mode 100644 index 000000000..79012ab03 --- /dev/null +++ b/src/ui/components/elements-inspector/ElementsInspector.tsx @@ -0,0 +1,106 @@ +/** + * Copyright 2018-present Facebook. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @format + */ + +import {Component} from 'react'; +import {Elements, DecorateRow} from './elements'; +import {ContextMenuExtension} from 'flipper'; +import React from 'react'; + +export type ElementID = string; + +export type ElementSearchResultSet = { + query: string; + matches: Set; +}; + +export type ElementData = { + [name: string]: { + [key: string]: + | string + | number + | boolean + | { + __type__: string; + value: any; + }; + }; +}; + +export type ElementAttribute = { + name: string; + value: string; +}; + +export type ElementExtraInfo = { + linkedNode?: string; // id of linked node in opposite tree + expandWithParent?: boolean; +}; + +export type Element = { + id: ElementID; + name: string; + expanded: boolean; + children: Array; + attributes: Array; + data: ElementData; + decoration: string; + extraInfo: ElementExtraInfo; +}; + +export default class ElementsInspector extends Component<{ + onElementExpanded: (key: ElementID, deep: boolean) => void; + onElementSelected: (key: ElementID) => void; + onElementHovered: + | ((key: ElementID | undefined | null) => any) + | undefined + | null; + onValueChanged: ((path: Array, val: any) => any) | undefined | null; + selected: ElementID | undefined | null; + focused?: ElementID | undefined | null; + searchResults?: ElementSearchResultSet | undefined | null; + root: ElementID | undefined | null; + elements: {[key: string]: Element}; + useAppSidebar?: boolean; + alternateRowColor?: boolean; + contextMenuExtensions?: Array; + decorateRow?: DecorateRow; +}> { + static defaultProps = { + alternateRowColor: true, + }; + render() { + const { + selected, + focused, + elements, + root, + onElementExpanded, + onElementSelected, + onElementHovered, + searchResults, + alternateRowColor, + contextMenuExtensions, + decorateRow, + } = this.props; + + return ( + + ); + } +} diff --git a/src/ui/components/elements-inspector/elements.js b/src/ui/components/elements-inspector/elements.tsx similarity index 81% rename from src/ui/components/elements-inspector/elements.js rename to src/ui/components/elements-inspector/elements.tsx index b981c694c..332712b2e 100644 --- a/src/ui/components/elements-inspector/elements.js +++ b/src/ui/components/elements-inspector/elements.tsx @@ -5,25 +5,27 @@ * @format */ -import type { - ElementID, - Element, - ElementSearchResultSet, -} from './ElementsInspector.js'; -import {reportInteraction} from '../../../utils/InteractionTracker.tsx'; -import ContextMenu from '../ContextMenu.tsx'; -import {PureComponent, type Element as ReactElement} from 'react'; -import FlexRow from '../FlexRow.tsx'; -import FlexColumn from '../FlexColumn.tsx'; -import Glyph from '../Glyph.tsx'; -import {colors} from '../colors.tsx'; -import Text from '../Text.tsx'; -import styled from '../../styled/index.js'; -import {clipboard} from 'electron'; +import {ElementID, Element, ElementSearchResultSet} from './ElementsInspector'; +import {reportInteraction} from '../../../utils/InteractionTracker'; +import ContextMenu from '../ContextMenu'; +import {PureComponent, ReactElement} from 'react'; +import FlexRow from '../FlexRow'; +import FlexColumn from '../FlexColumn'; +import Glyph from '../Glyph'; +import {colors} from '../colors'; +import Text from '../Text'; +import styled from 'react-emotion'; +import {clipboard, MenuItemConstructorOptions} from 'electron'; +import React, {MouseEvent, KeyboardEvent} from 'react'; const ROW_HEIGHT = 23; -const backgroundColor = props => { +const backgroundColor = (props: { + selected: boolean; + focused: boolean; + isQueryMatch: boolean; + even: boolean; +}) => { if (props.selected) { return colors.macOSTitleBarIconSelected; } else if (props.isQueryMatch) { @@ -37,7 +39,7 @@ const backgroundColor = props => { } }; -const backgroundColorHover = props => { +const backgroundColorHover = (props: {selected: boolean; focused: boolean}) => { if (props.selected) { return colors.macOSTitleBarIconSelected; } else if (props.focused) { @@ -47,7 +49,7 @@ const backgroundColorHover = props => { } }; -const ElementsRowContainer = styled(ContextMenu)(props => ({ +const ElementsRowContainer = styled(ContextMenu)((props: any) => ({ flexDirection: 'row', alignItems: 'center', backgroundColor: backgroundColor(props), @@ -79,7 +81,7 @@ const ElementsRowDecoration = styled(FlexRow)({ top: -1, }); -const ElementsLine = styled('div')(props => ({ +const ElementsLine = styled('div')((props: {childrenCount: number}) => ({ backgroundColor: colors.light20, height: props.childrenCount * ROW_HEIGHT - 4, position: 'absolute', @@ -119,13 +121,13 @@ const ElementsRowAttributeValue = styled('span')({ }); class PartialHighlight extends PureComponent<{ - selected: boolean, - highlighted: ?string, - content: string, + selected: boolean; + highlighted: string | undefined | null; + content: string; }> { - static HighlightedText = styled('span')(({selected}) => ({ + static HighlightedText = styled('span')((props: {selected: boolean}) => ({ backgroundColor: colors.lemon, - color: selected ? `${colors.grapeDark3} !important` : 'auto', + color: props.selected ? `${colors.grapeDark3} !important` : 'auto', })); render() { @@ -161,10 +163,10 @@ class PartialHighlight extends PureComponent<{ } class ElementsRowAttribute extends PureComponent<{ - name: string, - value: string, - matchingSearchQuery: ?string, - selected: boolean, + name: string; + value: string; + matchingSearchQuery: string | undefined | null; + selected: boolean; }> { render() { const {name, value, matchingSearchQuery, selected} = this.props; @@ -185,35 +187,38 @@ class ElementsRowAttribute extends PureComponent<{ } } -type FlatElement = {| - key: ElementID, - element: Element, - level: number, -|}; +type FlatElement = { + key: ElementID; + element: Element; + level: number; +}; type FlatElements = Array; type ElementsRowProps = { - id: ElementID, - level: number, - selected: boolean, - focused: boolean, - matchingSearchQuery: ?string, - isQueryMatch: boolean, - element: Element, - even: boolean, - onElementSelected: (key: ElementID) => void, - onElementExpanded: (key: ElementID, deep: boolean) => void, - childrenCount: number, - onElementHovered: ?(key: ?ElementID) => void, - style?: Object, - contextMenuExtensions: Array, - decorateRow?: DecorateRow, + id: ElementID; + level: number; + selected: boolean; + focused: boolean; + matchingSearchQuery: string | undefined | null; + isQueryMatch: boolean; + element: Element; + even: boolean; + onElementSelected: (key: ElementID) => void; + onElementExpanded: (key: ElementID, deep: boolean) => void; + childrenCount: number; + onElementHovered: + | ((key: ElementID | undefined | null) => void) + | undefined + | null; + style?: Object; + contextMenuExtensions: Array; + decorateRow?: DecorateRow; }; -type ElementsRowState = {| - hovered: boolean, -|}; +type ElementsRowState = { + hovered: boolean; +}; class ElementsRow extends PureComponent { constructor(props: ElementsRowProps, context: Object) { @@ -226,7 +231,7 @@ class ElementsRow extends PureComponent { getContextMenu = (): Array => { const {props} = this; - const items = [ + const items: Array = [ { type: 'separator', }, @@ -259,7 +264,7 @@ class ElementsRow extends PureComponent { this.interaction('selected', {level: this.props.level}); }; - onDoubleClick = (event: SyntheticMouseEvent<*>) => { + onDoubleClick = (event: MouseEvent) => { this.props.onElementExpanded(this.props.id, event.altKey); }; @@ -307,12 +312,10 @@ class ElementsRow extends PureComponent { const attributes = element.attributes ? element.attributes.map(attr => ( )) : []; @@ -377,7 +380,7 @@ class ElementsRow extends PureComponent { } function containsKeyInSearchResults( - searchResults: ?ElementSearchResultSet, + searchResults: ElementSearchResultSet | undefined | null, key: ElementID, ) { return searchResults != undefined && searchResults.matches.has(key); @@ -396,32 +399,35 @@ const ElementsBox = styled(FlexColumn)({ overflow: 'auto', }); -export type DecorateRow = Element => ?ReactElement; +export type DecorateRow = (e: Element) => ReactElement | undefined | null; -type ElementsProps = {| - root: ?ElementID, - selected: ?ElementID, - focused?: ?ElementID, - searchResults: ?ElementSearchResultSet, - elements: {[key: ElementID]: Element}, - onElementSelected: (key: ElementID) => void, - onElementExpanded: (key: ElementID, deep: boolean) => void, - onElementHovered: ?(key: ?ElementID) => void, - alternateRowColor?: boolean, - contextMenuExtensions?: Array, - decorateRow?: DecorateRow, -|}; +type ElementsProps = { + root: ElementID | undefined | null; + selected: ElementID | undefined | null; + focused?: ElementID | undefined | null; + searchResults: ElementSearchResultSet | undefined | null; + elements: {[key: string]: Element}; + onElementSelected: (key: ElementID) => void; + onElementExpanded: (key: ElementID, deep: boolean) => void; + onElementHovered: + | ((key: ElementID | undefined | null) => void) + | undefined + | null; + alternateRowColor?: boolean; + contextMenuExtensions?: Array; + decorateRow?: DecorateRow; +}; -type ElementsState = {| - flatKeys: Array, - flatElements: FlatElements, - maxDepth: number, -|}; +type ElementsState = { + flatKeys: Array; + flatElements: FlatElements; + maxDepth: number; +}; -export type ContextMenuExtension = {| - label: string, - click: ElementID => void, -|}; +export type ContextMenuExtension = { + label: string; + click: (element: ElementID) => any; +}; export class Elements extends PureComponent { static defaultProps = { @@ -437,14 +443,14 @@ export class Elements extends PureComponent { } componentDidMount() { - this.setProps(this.props, true); + this.setProps(this.props); } componentWillReceiveProps(nextProps: ElementsProps) { this.setProps(nextProps); } - setProps(props: ElementsProps, force?: boolean) { + setProps(props: ElementsProps) { const flatElements: FlatElements = []; const flatKeys = []; @@ -488,7 +494,7 @@ export class Elements extends PureComponent { this.props.onElementSelected(key); }; - onKeyDown = (e: SyntheticKeyboardEvent<*>) => { + onKeyDown = (e: KeyboardEvent) => { const {selected} = this.props; if (selected == null) { return; @@ -572,7 +578,6 @@ export class Elements extends PureComponent { buildRow = (row: FlatElement, index: number) => { const { - elements, onElementExpanded, onElementHovered, onElementSelected, @@ -618,7 +623,6 @@ export class Elements extends PureComponent { } isQueryMatch={containsKeyInSearchResults(searchResults, row.key)} element={row.element} - elements={elements} childrenCount={childrenCount} contextMenuExtensions={contextMenuExtensions || []} decorateRow={decorateRow} @@ -629,7 +633,7 @@ export class Elements extends PureComponent { render() { return ( - + {this.state.flatElements.map(this.buildRow)} diff --git a/src/ui/components/elements-inspector/sidebar.js b/src/ui/components/elements-inspector/sidebar.tsx similarity index 84% rename from src/ui/components/elements-inspector/sidebar.js rename to src/ui/components/elements-inspector/sidebar.tsx index 3be4daa32..71b7a5719 100644 --- a/src/ui/components/elements-inspector/sidebar.js +++ b/src/ui/components/elements-inspector/sidebar.tsx @@ -5,25 +5,26 @@ * @format */ -import type {Element} from './ElementsInspector.js'; -import type {PluginClient} from '../../../plugin.tsx'; -import type Client from '../../../Client.tsx'; -import type {Logger} from '../../../fb-interfaces/Logger.js'; -import Panel from '../Panel.tsx'; -import ManagedDataInspector from '../data-inspector/ManagedDataInspector.tsx'; +import {Element} from './ElementsInspector'; +import {PluginClient} from '../../../plugin'; +import Client from '../../../Client'; +import {Logger} from '../../../fb-interfaces/Logger.js'; +import Panel from '../Panel'; +import ManagedDataInspector from '../data-inspector/ManagedDataInspector'; import {Component} from 'react'; -import {Console} from '../console.tsx'; -import GK from '../../../fb-stubs/GK.tsx'; +import {Console} from '../console'; +import GK from '../../../fb-stubs/GK'; +import React from 'react'; -const deepEqual = require('deep-equal'); +import deepEqual from 'deep-equal'; type OnValueChanged = (path: Array, val: any) => void; type InspectorSidebarSectionProps = { - data: any, - id: string, - onValueChanged: ?OnValueChanged, - tooltips?: Object, + data: any; + id: string; + onValueChanged: OnValueChanged | undefined | null; + tooltips?: Object; }; class InspectorSidebarSection extends Component { @@ -74,19 +75,19 @@ class InspectorSidebarSection extends Component { } } -type Props = {| - element: ?Element, - tooltips?: Object, - onValueChanged: ?OnValueChanged, - client: PluginClient, - realClient: Client, - logger: Logger, - extensions?: Array, -|}; +type Props = { + element: Element | undefined | null; + tooltips?: Object; + onValueChanged: OnValueChanged | undefined | null; + client: PluginClient; + realClient: Client; + logger: Logger; + extensions?: Array; +}; -type State = {| - isConsoleEnabled: boolean, -|}; +type State = { + isConsoleEnabled: boolean; +}; export class InspectorSidebar extends Component { state = { @@ -144,7 +145,7 @@ export class InspectorSidebar extends Component { console.error( `ElementsInspector unable to parse extra section: ${extraSection}`, ); - data = {}; + data = null; } } sections.push( diff --git a/src/ui/index.js b/src/ui/index.js index 4ca0571db..5ab7fa4be 100644 --- a/src/ui/index.js +++ b/src/ui/index.js @@ -170,15 +170,15 @@ export type { ElementAttribute, Element, ElementSearchResultSet, -} from './components/elements-inspector/ElementsInspector.js'; -export {Elements} from './components/elements-inspector/elements.js'; +} from './components/elements-inspector/ElementsInspector.tsx'; +export {Elements} from './components/elements-inspector/elements.tsx'; export type { ContextMenuExtension, -} from './components/elements-inspector/elements.js'; +} from './components/elements-inspector/elements.tsx'; export { default as ElementsInspector, -} from './components/elements-inspector/ElementsInspector.js'; -export {InspectorSidebar} from './components/elements-inspector/sidebar.js'; +} from './components/elements-inspector/ElementsInspector.tsx'; +export {InspectorSidebar} from './components/elements-inspector/sidebar.tsx'; export {Console} from './components/console.tsx';