mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Adds inspectable event components + props
[Flare] Adds inspectable event components + props
This commit is contained in:
committed by
Brian Vaughn
parent
e4aa3c5b33
commit
779fd167ff
@@ -17,6 +17,7 @@ export function print(inspectedElement, serialize, indent) {
|
||||
id: inspectedElement.id,
|
||||
owners: inspectedElement.owners,
|
||||
context: inspectedElement.context,
|
||||
events: inspectedElement.events,
|
||||
hooks: inspectedElement.hooks,
|
||||
props: inspectedElement.props,
|
||||
state: inspectedElement.state,
|
||||
|
||||
@@ -478,6 +478,10 @@ export function attach(
|
||||
case EVENT_TARGET_TOUCH_HIT_STRING:
|
||||
return 'TouchHitTarget';
|
||||
default:
|
||||
const displayName = elementType.displayName;
|
||||
if (displayName !== undefined) {
|
||||
return displayName;
|
||||
}
|
||||
return 'EventTarget';
|
||||
}
|
||||
case ForwardRef:
|
||||
@@ -1833,6 +1837,23 @@ export function attach(
|
||||
const isTimedOutSuspense =
|
||||
tag === SuspenseComponent && memoizedState !== null;
|
||||
|
||||
let events = null;
|
||||
let node = fiber;
|
||||
while (node !== null) {
|
||||
if (node.tag === EventComponent) {
|
||||
if (events === null) {
|
||||
events = [];
|
||||
}
|
||||
const eventComponentInstance = node.stateNode;
|
||||
const currentFiber = eventComponentInstance.currentFiber;
|
||||
events.push({
|
||||
props: eventComponentInstance.props,
|
||||
displayName: currentFiber.type.displayName,
|
||||
});
|
||||
}
|
||||
node = node.return;
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
|
||||
@@ -1858,6 +1879,7 @@ export function attach(
|
||||
// Inspectable properties.
|
||||
// TODO Review sanitization approach for the below inspectable values.
|
||||
context,
|
||||
events,
|
||||
hooks: usesHooks
|
||||
? inspectHooksOfFiber(fiber, (renderer.currentDispatcherRef: any))
|
||||
: null,
|
||||
@@ -1879,6 +1901,7 @@ export function attach(
|
||||
}
|
||||
// TODO Review sanitization approach for the below inspectable values.
|
||||
result.context = cleanForBridge(result.context);
|
||||
result.events = cleanForBridge(result.events);
|
||||
result.hooks = cleanForBridge(result.hooks);
|
||||
result.props = cleanForBridge(result.props);
|
||||
result.state = cleanForBridge(result.state);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
.EventsTree {
|
||||
padding: 0.25rem;
|
||||
border-top: 1px solid var(--color-border);
|
||||
}
|
||||
.EventsTree:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.HeaderRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Header {
|
||||
flex: 1 1;
|
||||
font-family: var(--font-family-sans);
|
||||
}
|
||||
|
||||
.NameValueRow {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.Empty {
|
||||
color: var(--color-dimmer);
|
||||
font-style: italic;
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import { copy } from 'clipboard-js';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import styles from './EventsTree.css';
|
||||
import Button from '../Button';
|
||||
import ButtonIcon from '../ButtonIcon';
|
||||
import KeyValue from './KeyValue';
|
||||
import ExpandCollapseToggle from './ExpandCollapseToggle';
|
||||
import { serializeDataForCopy } from '../utils';
|
||||
|
||||
type Props = {|
|
||||
events: Object,
|
||||
|};
|
||||
|
||||
function EventsTreeView({ events }: Props) {
|
||||
const handleCopy = useCallback(() => copy(serializeDataForCopy(events)), [
|
||||
events,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className={styles.EventsTree}>
|
||||
<div className={styles.HeaderRow}>
|
||||
<div className={styles.Header}>events</div>
|
||||
{
|
||||
<Button onClick={handleCopy} title="Copy to clipboard">
|
||||
<ButtonIcon type="copy" />
|
||||
</Button>
|
||||
}
|
||||
</div>
|
||||
<InnerEventsTreeView events={events} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function InnerEventsTreeView({ events }: Props) {
|
||||
return events.map((event, index) => (
|
||||
<EventComponentView
|
||||
key={index}
|
||||
displayName={event.displayName}
|
||||
props={event.props}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
type EventComponentViewProps = {|
|
||||
displayName: string,
|
||||
props: null | Object,
|
||||
|};
|
||||
|
||||
function EventComponentView({ displayName, props }: EventComponentViewProps) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
let eventComponentProps = null;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let children;
|
||||
|
||||
if (props !== null) {
|
||||
// We don't want children, so extract it out
|
||||
({ children, ...eventComponentProps } = props);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.NameValueRow}>
|
||||
<ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />
|
||||
<span onClick={() => {}} className={styles.Name}>
|
||||
{displayName}
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.Children} hidden={!isOpen}>
|
||||
{eventComponentProps === null && (
|
||||
<div className={styles.Empty}>None</div>
|
||||
)}
|
||||
{eventComponentProps !== null &&
|
||||
Object.keys((eventComponentProps: any)).map(name => (
|
||||
<KeyValue
|
||||
key={name}
|
||||
depth={1}
|
||||
name={name}
|
||||
path={[name]}
|
||||
value={(eventComponentProps: any)[name]}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// $FlowFixMe
|
||||
export default React.memo(EventsTreeView);
|
||||
@@ -90,6 +90,7 @@ function InspectedElementContextController({ children }: Props) {
|
||||
inspectedElement = (({
|
||||
...inspectedElement,
|
||||
context: hydrateHelper(inspectedElement.context),
|
||||
events: hydrateHelper(inspectedElement.events),
|
||||
hooks: hydrateHelper(inspectedElement.hooks),
|
||||
props: hydrateHelper(inspectedElement.props),
|
||||
state: hydrateHelper(inspectedElement.state),
|
||||
|
||||
@@ -6,6 +6,7 @@ import { BridgeContext, StoreContext } from '../context';
|
||||
import Button from '../Button';
|
||||
import ButtonIcon from '../ButtonIcon';
|
||||
import HooksTree from './HooksTree';
|
||||
import EventsTree from './EventsTree';
|
||||
import { ModalDialogContext } from '../ModalDialog';
|
||||
import InspectedElementTree from './InspectedElementTree';
|
||||
import { InspectedElementContext } from './InspectedElementContext';
|
||||
@@ -221,6 +222,7 @@ function InspectedElementView({
|
||||
canEditHooks,
|
||||
canToggleSuspense,
|
||||
context,
|
||||
events,
|
||||
hooks,
|
||||
owners,
|
||||
props,
|
||||
@@ -297,6 +299,7 @@ function InspectedElementView({
|
||||
data={context}
|
||||
overrideValueFn={overrideContextFn}
|
||||
/>
|
||||
{events !== null && events.length > 0 && <EventsTree events={events} />}
|
||||
|
||||
{ownerID === null && owners !== null && owners.length > 0 && (
|
||||
<div className={styles.Owners}>
|
||||
|
||||
@@ -59,6 +59,7 @@ export type InspectedElement = {|
|
||||
|
||||
// Inspectable properties.
|
||||
context: Object | null,
|
||||
events: Object | null,
|
||||
hooks: Object | null,
|
||||
props: Object | null,
|
||||
state: Object | null,
|
||||
|
||||
Reference in New Issue
Block a user