Retrofit the AddressHighlighter into the new generic SelectionHighlighter
This commit is contained in:
parent
ad94813476
commit
09e89c5f41
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from "react";
|
||||
import { useSelectionContext } from "../useSelection";
|
||||
import React from "react";
|
||||
import SelectionHighlighter, { addressSelector } from "./SelectionHighlighter";
|
||||
|
||||
type AddressHighlighterProps = React.PropsWithChildren<{
|
||||
address: string;
|
||||
|
@ -8,50 +8,14 @@ type AddressHighlighterProps = React.PropsWithChildren<{
|
|||
const AddressHighlighter: React.FC<AddressHighlighterProps> = ({
|
||||
address,
|
||||
children,
|
||||
}) => {
|
||||
const [selection, setSelection] = useSelectionContext();
|
||||
const [select, deselect] = useMemo(() => {
|
||||
const _select = () => {
|
||||
setSelection({ type: "address", content: address });
|
||||
};
|
||||
const _deselect = () => {
|
||||
setSelection(null);
|
||||
};
|
||||
return [_select, _deselect];
|
||||
}, [setSelection, address]);
|
||||
|
||||
return (
|
||||
<AddressHighlighterImpl
|
||||
selected={
|
||||
selection !== null &&
|
||||
selection.type === "address" &&
|
||||
selection.content === address
|
||||
}
|
||||
select={select}
|
||||
deselect={deselect}
|
||||
>
|
||||
{children}
|
||||
</AddressHighlighterImpl>
|
||||
);
|
||||
};
|
||||
|
||||
type _AddressHighlighterImplProps = {
|
||||
selected: boolean;
|
||||
select: () => void;
|
||||
deselect: () => void;
|
||||
};
|
||||
|
||||
const AddressHighlighterImpl: React.FC<_AddressHighlighterImplProps> =
|
||||
React.memo(({ selected, select, deselect, children }) => (
|
||||
<div
|
||||
className={`border border-dashed rounded hover:bg-transparent hover:border-transparent px-1 truncate ${
|
||||
selected ? "border-orange-400 bg-yellow-100" : "border-transparent"
|
||||
}`}
|
||||
onMouseEnter={select}
|
||||
onMouseLeave={deselect}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
));
|
||||
}) => (
|
||||
<SelectionHighlighter
|
||||
myType="address"
|
||||
myContent={address}
|
||||
selector={addressSelector}
|
||||
>
|
||||
{children}
|
||||
</SelectionHighlighter>
|
||||
);
|
||||
|
||||
export default AddressHighlighter;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import React, { useMemo } from "react";
|
||||
import {
|
||||
useSelectionContext,
|
||||
OptionalSelection,
|
||||
SelectionType,
|
||||
} from "../useSelection";
|
||||
|
||||
export type ContentSelector = (
|
||||
selection: OptionalSelection,
|
||||
content: string
|
||||
) => boolean;
|
||||
|
||||
export const genericSelector =
|
||||
(type: SelectionType) =>
|
||||
(selection: OptionalSelection, content: string): boolean =>
|
||||
selection !== null &&
|
||||
selection.type === type &&
|
||||
selection.content === content;
|
||||
|
||||
export const addressSelector: ContentSelector = genericSelector("address");
|
||||
|
||||
type SelectionHighlighterProps = React.PropsWithChildren<{
|
||||
myType: SelectionType;
|
||||
myContent: string;
|
||||
selector: ContentSelector;
|
||||
}>;
|
||||
|
||||
const SelectionHighlighter: React.FC<SelectionHighlighterProps> = ({
|
||||
myType,
|
||||
myContent,
|
||||
selector,
|
||||
children,
|
||||
}) => {
|
||||
const [selection, setSelection] = useSelectionContext();
|
||||
const [select, deselect] = useMemo(() => {
|
||||
const _select = () => {
|
||||
setSelection({ type: myType, content: myContent });
|
||||
};
|
||||
const _deselect = () => {
|
||||
setSelection(null);
|
||||
};
|
||||
return [_select, _deselect];
|
||||
}, [setSelection, myType, myContent]);
|
||||
|
||||
return (
|
||||
<HighlighterBox
|
||||
selected={selector(selection, myContent)}
|
||||
select={select}
|
||||
deselect={deselect}
|
||||
>
|
||||
{children}
|
||||
</HighlighterBox>
|
||||
);
|
||||
};
|
||||
|
||||
type HighlighterBoxProps = {
|
||||
selected: boolean;
|
||||
select: () => void;
|
||||
deselect: () => void;
|
||||
};
|
||||
|
||||
const HighlighterBox: React.FC<HighlighterBoxProps> = React.memo(
|
||||
({ selected, select, deselect, children }) => (
|
||||
<div
|
||||
className={`border border-dashed rounded hover:bg-transparent hover:border-transparent px-1 truncate ${
|
||||
selected ? "border-orange-400 bg-yellow-100" : "border-transparent"
|
||||
}`}
|
||||
onMouseEnter={select}
|
||||
onMouseLeave={deselect}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
export default SelectionHighlighter;
|
|
@ -0,0 +1,25 @@
|
|||
import React from "react";
|
||||
|
||||
type FunctionSignatureProps = {
|
||||
callType: string;
|
||||
sig: string;
|
||||
};
|
||||
|
||||
const FunctionSignature: React.FC<FunctionSignatureProps> = ({
|
||||
callType,
|
||||
sig,
|
||||
}) => (
|
||||
<span
|
||||
className={`font-bold ${
|
||||
callType === "STATICCALL"
|
||||
? "text-red-700"
|
||||
: callType === "DELEGATECALL" || callType === "CALLCODE"
|
||||
? "text-gray-400"
|
||||
: "text-blue-900"
|
||||
}`}
|
||||
>
|
||||
{sig}
|
||||
</span>
|
||||
);
|
||||
|
||||
export default FunctionSignature;
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import AddressHighlighter from "../components/AddressHighlighter";
|
||||
import DecoratedAddressLink from "../components/DecoratedAddressLink";
|
||||
import FormattedBalance from "../components/FormattedBalance";
|
||||
import FunctionSignature from "./FunctionSignature";
|
||||
import { TransactionData } from "../types";
|
||||
import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes";
|
||||
import { TraceGroup } from "../useErigonHooks";
|
||||
|
@ -38,17 +39,10 @@ const TraceItem: React.FC<TraceItemProps> = ({ t, txData, last }) => {
|
|||
</AddressHighlighter>
|
||||
</span>
|
||||
<span>.</span>
|
||||
<span
|
||||
className={`font-bold ${
|
||||
t.type === "STATICCALL"
|
||||
? "text-red-700"
|
||||
: t.type === "DELEGATECALL" || t.type === "CALLCODE"
|
||||
? "text-gray-400"
|
||||
: "text-blue-900"
|
||||
}`}
|
||||
>
|
||||
{fourBytesEntry ? fourBytesEntry.name : raw4Bytes}
|
||||
</span>
|
||||
<FunctionSignature
|
||||
callType={t.type}
|
||||
sig={fourBytesEntry ? fourBytesEntry.name : raw4Bytes}
|
||||
/>
|
||||
{t.value && !t.value.isZero() && (
|
||||
<span className="text-red-700 whitespace-nowrap">
|
||||
{"{"}value: <FormattedBalance value={t.value} /> ETH{"}"}
|
||||
|
|
|
@ -6,12 +6,14 @@ import {
|
|||
useContext,
|
||||
} from "react";
|
||||
|
||||
export type SelectionType = "address" | "value" | "functionSig";
|
||||
|
||||
export type Selection = {
|
||||
type: "address" | "value";
|
||||
type: SelectionType;
|
||||
content: string;
|
||||
};
|
||||
|
||||
type OptionalSelection = Selection | null;
|
||||
export type OptionalSelection = Selection | null;
|
||||
|
||||
export const useSelection = (): [
|
||||
OptionalSelection,
|
||||
|
|
Loading…
Reference in New Issue