import { BinaryEditModal } from "@/components/BinaryEditButton" import { BinaryEdit, Focus, TypeIcon, TypeIcons } from "@/components/Icons" import { EditAccountId, EditBigNumber, EditBitSeq, EditBool, EditBytes, EditEthAccount, EditFixedBytes, EditNumber, EditOption, EditPrimitiveComponentProps, EditResult, EditStr, EditVoid, NOTIN, } from "@polkadot-api/react-builder" import { HexString } from "@polkadot-api/substrate-bindings" import { useStateObservable } from "@react-rxjs/core" import { Circle } from "lucide-react" import { createContext, FC, PropsWithChildren, ReactElement, useContext, useLayoutEffect, useState, } from "react" import { twMerge } from "tailwind-merge" import { isActive$, PathsRoot, setHovered } from "../../common/paths.state" export const CVoid: EditVoid = () => null const CPrimitive: FC> = ({ type, encodedValue, onValueChanged, decode, }) => { useReportBinaryStatus(type, encodedValue, onValueChanged, decode) return null } export const CBool: EditBool = CPrimitive export const CStr: EditStr = CPrimitive export const CEthAccount: EditEthAccount = CPrimitive export const CBigNumber: EditBigNumber = CPrimitive export const CNumber: EditNumber = CPrimitive export const CAccountId: EditAccountId = CPrimitive export const CBytes: EditBytes = CPrimitive export const CFixedBytes: EditFixedBytes = CPrimitive export const CBitSeq: EditBitSeq = CPrimitive export const COption: EditOption = ({ value, inner, type, encodedValue, onValueChanged, decode, }) => { useReportBinaryStatus(type, encodedValue, onValueChanged, decode) return value === undefined ? null : ( {}}> {inner} ) } export const CResult: EditResult = ({ value, inner }) => ( <> {value !== NOTIN && (value.success ? "ok" : "ko")}-{inner} ) export const ItemMarker = () => ( ) export const TitleContext = createContext(null) export type BinaryStatus = { type: "blank" | "partial" | "complete" encodedValue: Uint8Array | undefined onValueChanged: (value: any | NOTIN) => boolean decode: (value: Uint8Array | HexString) => any | NOTIN } export const BinaryStatusContext = createContext< (status: BinaryStatus) => void >(() => {}) export const useReportBinaryStatus = ( type: "blank" | "partial" | "complete", encodedValue: Uint8Array | undefined, onValueChanged: (value: any | NOTIN) => boolean, decode: (value: Uint8Array | HexString) => any | NOTIN, ) => { const onBinChange = useContext(BinaryStatusContext) useLayoutEffect( () => onBinChange({ type, encodedValue, onValueChanged, decode }), [type, encodedValue, onValueChanged, decode, onBinChange], ) } export const ChildrenProviders: FC< PropsWithChildren<{ onValueChange: (status: BinaryStatus) => void titleElement: HTMLElement | null }> > = ({ onValueChange, titleElement, children }) => ( {children} ) export const ItemTitle: FC< PropsWithChildren<{ path: string icon: (typeof TypeIcons)[TypeIcon] binaryStatus?: BinaryStatus onNavigate?: () => void titleRef?: (element: HTMLDivElement) => void onZoom?: () => void actions?: ReactElement className?: string }> > = ({ children, path, icon: Icon, binaryStatus, titleRef, onNavigate, onZoom, actions, className, }) => { const [binaryOpen, setBinaryOpen] = useState(false) const isActive = useStateObservable(isActive$(path)) const pathId = useContext(PathsRoot) return ( <>
setHovered(pathId, { id: path, hover: true })} onMouseLeave={() => setHovered(pathId, { id: path, hover: false })} > {children}
{onZoom && binaryStatus && ( setBinaryOpen(true)} /> )} {onZoom && ( )} {actions}
{binaryStatus && ( setBinaryOpen(false)} /> )} ) } const TreeBinaryEditModal: FC<{ status: BinaryStatus open: boolean path: string onClose: () => void }> = ({ status, path, open, onClose }) => ( )