import {Box, BoxProps, Card, Code, Label, Stack} from '@sanity/ui' import React, {useCallback, useEffect, useRef, useState} from 'react' import styled, {DefaultTheme, StyledComponent} from 'styled-components' import {pathToString} from '../../paths' import {FieldChangeNode} from '../../types' import {FromToArrow} from './FromToArrow' interface Props extends BoxProps { children: React.ReactNode change: FieldChangeNode as?: StyledComponent<'div', DefaultTheme> } const CodeWrapper = styled.pre` overflow-x: auto; position: relative; ` const Meta = styled.div` position: absolute; top: 0; right: 0; ` export function DiffInspectWrapper({ children, as, change, ...restProps }: Props): React.ReactElement { const isHovering = useRef(false) const [isInspecting, setIsInspecting] = useState(false) const toggleInspect = useCallback(() => setIsInspecting((state) => !state), [setIsInspecting]) const handleMouseEnter = useCallback(() => (isHovering.current = true), []) const handleMouseLeave = useCallback(() => (isHovering.current = false), [isHovering]) useEffect(() => { function onKeyDown(evt: KeyboardEvent) { const {metaKey, key} = evt if (metaKey && key === 'i' && isHovering.current) { toggleInspect() } } window.addEventListener('keydown', onKeyDown, false) return () => window.removeEventListener('keydown', onKeyDown, false) }, [toggleInspect]) return ( {isInspecting ? : children} ) } const MetaLabel = ({title}: {title: string}) => ( ) function DiffInspector({change}: {change: FieldChangeNode}): React.ReactElement | null { return ( {printMeta({ path: pathToString(change.path), fromIndex: change.itemDiff?.fromIndex, toIndex: change.itemDiff?.toIndex, hasMoved: change.itemDiff?.hasMoved, action: change.diff.action, isChanged: change.diff.isChanged, })} {jsonify(change.diff.fromValue)} {jsonify(change.diff.toValue)} ) } function jsonify(value: unknown) { if (typeof value === 'undefined') { return 'undefined' } return JSON.stringify(value, null, 2) } function printMeta(keys: Record) { const lines: string[] = [] Object.entries(keys).forEach(([key, value]) => { if (typeof value !== 'undefined' && value !== null) { lines.push(`${key}: ${value}`) } }) return lines.join('\n') }