import React from 'react';
import _ from 'lodash';
import cx from 'classnames';
import { ToolTip } from '@/_components/ToolTip';
import CopyToClipboardComponent from '@/_components/CopyToClipboard';
import { Popover } from 'react-bootstrap';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import JSONNodeObject from './JSONNodeObject';
import JSONNodeArray from './JSONNodeArray';
import JSONNodeValue from './JSONNodeValue';
import JSONNodeIndicator from './JSONNodeIndicator';
export const JSONNode = ({ data, ...restProps }) => {
const {
path,
shouldExpandNode,
currentNode,
selectedNode,
hoveredNode,
getCurrentPath,
getCurrentNodeType,
getLength,
toUseNodeIcons,
renderNodeIcons,
useIndentedBlock,
updateSelectedNode,
updateHoveredNode,
useActions,
enableCopyToClipboard,
getNodeShowHideComponents,
getOnSelectLabelDispatchActions,
expandWithLabels,
getAbsoluteNodePath,
actionsList,
updateParentState = () => null,
} = restProps;
const [expandable, set] = React.useState(() =>
typeof shouldExpandNode === 'function' ? shouldExpandNode(path, data) : shouldExpandNode
);
const [showHiddenOptionsForNode, setShowHiddenOptionsForNode] = React.useState(false);
const [showHiddenOptionButtons, setShowHiddenOptionButtons] = React.useState([]);
const [onSelectDispatchActions, setOnSelectDispatchActions] = React.useState([]);
React.useEffect(() => {
if (showHiddenOptionButtons) {
setShowHiddenOptionButtons(() => getNodeShowHideComponents(currentNode, path));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(() => {
if (useActions && currentNode) {
const onSelectDispatchActions = getOnSelectLabelDispatchActions(currentNode, path).filter(
(action) => action.onSelect
);
if (onSelectDispatchActions.length > 0) {
setOnSelectDispatchActions(onSelectDispatchActions);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedNode]);
const toggleExpandNode = (node) => {
if (expandable) {
updateSelectedNode(null);
} else {
updateSelectedNode(node, path);
}
set((prev) => !prev);
};
const onSelect = (data, currentNode, path) => {
const actions = onSelectDispatchActions;
actions.forEach((action) => action.dispatchAction(data, currentNode));
if (!expandWithLabels) {
updateSelectedNode(currentNode, path);
set(true);
}
};
const handleOnClickLabels = (data, currentNode, path) => {
if (expandWithLabels) {
toggleExpandNode(currentNode);
}
if (useActions) {
onSelect(data, currentNode, path);
}
};
const typeofCurrentNode = getCurrentNodeType(data);
const currentNodePath = getCurrentPath(path, currentNode);
const toExpandNode = (data instanceof Array || data instanceof Object) && !_.isEmpty(data);
const toShowNodeIndicator = (data instanceof Array || data instanceof Object) && typeofCurrentNode !== 'Function';
const numberOfEntries = getLength(typeofCurrentNode, data);
const toRenderSelector = (typeofCurrentNode === 'Object' || typeofCurrentNode === 'Array') && numberOfEntries > 0;
let $VALUE = null;
let $NODEType = null;
let $NODEIcon = null;
const checkSelectedNode = (_selectedNode, _currentNode, parent, toExpand) => {
if (selectedNode?.parent && parent) {
return _selectedNode.parent === parent && _selectedNode?.node === _currentNode && toExpand;
}
return toExpand && _selectedNode?.node === _currentNode;
};
const parent = path && typeof path?.length === 'number' ? path[path.length - 2] : null;
const applySelectedNodeStyles = toExpandNode
? checkSelectedNode(selectedNode, currentNode, parent, expandable)
: false;
React.useEffect(() => {
if (!expandable) {
updateSelectedNode(null);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [expandable]);
React.useEffect(() => {
if (selectedNode?.node === currentNode) {
set(true);
}
}, [selectedNode, currentNode]);
React.useEffect(() => {
if (hoveredNode?.node === currentNode && hoveredNode?.parent === parent) {
setShowHiddenOptionsForNode(true);
}
return () => {
setShowHiddenOptionsForNode(false);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hoveredNode]);
if (toUseNodeIcons && currentNode) {
$NODEIcon = renderNodeIcons(currentNode);
}
switch (typeofCurrentNode) {
case 'String':
case 'Boolean':
case 'Number':
case 'Null':
case 'Undefined':
case 'Function':
$VALUE =