<commit_before>import {BaseComponent, Div, Span, Instant, FindDOM, SimpleShouldUpdate, BaseProps, GetInnerComp, ShallowCompare, RenderSource, FindDOM_, ShallowEquals} from "../../../../Frame/UI/ReactGlobals";
import {connect} from "react-redux";
import {DBPath, GetData} from "../../../../Frame/Database/DatabaseHelpers";
import {Debugger, QuickIncrement, E, GetTimeSinceLoad} from "../../../../Frame/General/Globals_Free";
import Button from "../../../../Frame/ReactComponents/Button";
import {PropTypes, Component} from "react";
import Action from "../../../../Frame/General/Action";
import {Log} from "../../../../Frame/General/Logging";
import {WaitXThenRun} from "../../../../Frame/General/Timers";
import V from "../../../../Frame/V/V";
import * as VMenuTest1 from "react-vmenu";
import VMenu, {VMenuItem} from "react-vmenu";
import Select from "../../../../Frame/ReactComponents/Select";
import {GetEntries} from "../../../../Frame/General/Enums";
import {ShowMessageBox} from "../../../../Frame/UI/VMessageBox";
import TextInput from "../../../../Frame/ReactComponents/TextInput";
import {DN, ToJSON} from "../../../../Frame/General/Globals";
import {DataSnapshot} from "firebase";
import {styles} from "../../../../Frame/UI/GlobalStyles";
import {createSelector} from "reselect";
import NodeUI_Inner from "./NodeUI_Inner";
import {createMarkupForStyles} from "react-dom/lib/CSSPropertyOperations";
import NodeConnectorBackground from "./NodeConnectorBackground";
import {Vector2i} from "../../../../Frame/General/VectorStructs";
import {CachedTransform, CombineDynamicPropMaps} from "../../../../Frame/V/VCache";
import {RootState} from "../../../../Store/index";
import {GetNodeView} from "../../../../Store/main/mapViews";
import {MapNode, ThesisForm, MapNodeEnhanced} from "../../../../Store/firebase/nodes/@MapNode";
import {Map} from "../../../../Store/firebase/maps/@Map";
import {GetNodeChildren, GetParentNode, GetNodeChildrenEnhanced} from "../../../../Store/firebase/nodes";
import {MapNodeView} from "../../../../Store/main/mapViews/@MapViews";
import {MapNodeType, MapNodeType_Info} from "../../../../Store/firebase/nodes/@MapNodeType";
import {Connect} from "../../../../Frame/Database/FirebaseConnect";
import {GetFillPercentForRatingAverage, GetRatingAverage} from "../../../../Store/firebase/nodeRatings";
import Column from "../../../../Frame/ReactComponents/Column";
import { GetRatingTypesForNode, GetNodeDisplayText, GetFontSizeForNode, GetNodeForm, GetFinalNodeTypeAtPath, GetMainRatingType, GetNodeEnhanced, GetSortByRatingType, IsArgumentNode } from "../../../../Store/firebase/nodes/$node";
import * as FastDOM from "fastdom";

// modified version which only requests paths that do not yet exist in the store
/*export function Firebase_Connect(innerFirebaseConnect) {
	return firebaseConnect(props=> {
		let firebase = State().firebase;

		let innerPaths = innerFirebaseConnect(props) as string[];
		// if inner-paths are all already loaded, don't request the paths this time
		let innerPaths_unrequested = innerPaths.Where(path=>GetData(firebase, path) == null);
		/*Log(innerPaths.length + ";" + innerPaths_unrequested.length + "\n" + innerPaths + "\n" + innerPaths_unrequested);
		if (GetTimeSinceLoad() > 5)
			debugger;*#/
		return innerPaths_unrequested;
	});
}*/

let childrenPlaceholder = [];

type Props = {map: Map, node: MapNodeEnhanced, path?: string, widthOverride?: number, onHeightOrPosChange?: ()=>void}
	& Partial<{form: ThesisForm, nodeView: MapNodeView,
		nodeChildren: MapNodeEnhanced[],
		//nodeChildren_fillPercents: number[],
		nodeChildren_sortValues: number[],
	}>;
type State = {hasBeenExpanded: boolean, childrenWidthOverride: number, childrenCenterY: number, svgInfo: {mainBoxOffset: Vector2i, oldChildBoxOffsets: Vector2i[]}};
@Connect((state: RootState, {node, path, map}: Props & BaseProps)=> {
	//Log("Calling NodeUI connect func.");
	let nodeView = GetNodeView(map._id, path) || new MapNodeView();

	let nodeChildren = GetNodeChildrenEnhanced(node, path);
	// only pass nodeChildren when all are loaded
	nodeChildren = nodeChildren.Any(a=>a == null) ? childrenPlaceholder : nodeChildren;
	/*let nodeChildren_finalTypes = nodeChildren == childrenPlaceholder ? childrenPlaceholder : nodeChildren.map(child=> {
		return GetFinalNodeTypeAtPath(child, path + "/" + child._id);
	});*/

	let nodeChildren_sortValues = nodeChildren == childrenPlaceholder ? childrenPlaceholder : nodeChildren.map(child=> {
		return GetFillPercentForRatingAverage(child, GetRatingAverage(child._id, GetSortByRatingType(child)), GetNodeForm(child) == ThesisForm.Negation);
	});
	/*for (var i = 0; i < nodeChildren.length; i++) {
		let child = nodeChildren[i];
		if (child.chainAfter == "[start]") {
			nodeChildren_sortValues[i] = -1;
			continue;
		}
		let chainAfterNode = nodeChildren.FirstOrX(a=>a._id.toString() == child.chainAfter);
		if (chainAfterNode) {
			let chainAfterNode_sortValue = nodeChildren_sortValues[nodeChildren.indexOf(chainAfterNode)];
			nodeChildren_sortValues[i] = chainAfterNode_sortValue + .000001;
		}
	}*/
	let nodeChildren_fillPercents = nodeChildren == childrenPlaceholder ? childrenPlaceholder : nodeChildren.map(child=> {
		return GetFillPercentForRatingAverage(child, GetRatingAverage(child._id, GetMainRatingType(child)), GetNodeForm(child) == ThesisForm.Negation);
	});
	
	return {
		path: path || node._id.toString(),

		//node_finalType: GetFinalNodeTypeAtPath(node, path),
		//nodeEnhanced: GetNodeEnhanced(node, path),
		form: GetNodeForm(node, GetParentNode(path)),
		// only pass new nodeView when its local-props are different
		nodeView: CachedTransform("nodeView_transform1", [map._id, path], nodeView.Excluding("focus", "viewOffset", "children"), ()=>nodeView),
		/*nodeChildren: CachedTransform("nodeChildren_transform1", {path}, CombineDynamicPropMaps(nodeChildren, nodeChildren_finalTypes),
			()=>nodeChildren.map((child, index)=> {
				return child.Extended({finalType: nodeChildren_finalTypes[index]});
			})),*/
		nodeChildren,
		nodeChildren_sortValues: CachedTransform("nodeChildren_sortValues_transform1", [node._id], nodeChildren_sortValues, ()=>nodeChildren_sortValues),
		nodeChildren_fillPercents: CachedTransform("nodeChildren_fillPercents_transform1", [node._id], nodeChildren_fillPercents, ()=>nodeChildren_fillPercents),
	};
})
export default class NodeUI extends BaseComponent<Props, State> {
	static renderCount = 0;
	static lastRenderTime = -1;
	
	constructor(props) {
		super(props);
		this.state = {svgInfo: {}} as any;
	}
	ComponentWillMountOrReceiveProps(newProps) {
		let {nodeView} = newProps;
		if (nodeView && nodeView.expanded)
			this.SetState({hasBeenExpanded: true});
	}

	/*shouldComponentUpdate(nextProps, nextState) {
		debugger;
		return true;
	}*/

	render() {
		let {map, node, path, form, widthOverride, children, nodeView, nodeChildren, nodeChildren_sortValues} = this.props;
		let expanded = nodeView && nodeView.expanded;
		let {hasBeenExpanded, childrenWidthOverride, childrenCenterY, svgInfo} = this.state;
		//Log(`Updating NodeUI (${RenderSource[this.lastRender_source]}):${node._id};PropsChanged:${this.GetPropsChanged()};StateChanged:${this.GetStateChanged()}`);
		NodeUI.renderCount++;
		NodeUI.lastRenderTime = Date.now();

		let separateChildren = node.finalType == MapNodeType.Thesis;
		type ChildPack = {origIndex: number, node: MapNodeEnhanced, ui: JSX.Element};
		let childPacks: ChildPack[] = nodeChildren.map((child, index)=> {
			return {
				origIndex: index,
				node: child,
				ui: <NodeUI key={index} ref={c=>this.childBoxes[index] = c} map={map} node={child}
					path={path + "/" + child._id} widthOverride={childrenWidthOverride} onHeightOrPosChange={this.OnChildHeightOrPosChange}/>
			};
		});
		let upChildPacks = separateChildren ? childPacks.filter(a=>a.node.finalType == MapNodeType.SupportingArgument) : [];
		let downChildPacks = separateChildren ? childPacks.filter(a=>a.node.finalType == MapNodeType.OpposingArgument) : [];

		// apply sorting
		if (separateChildren) {
			upChildPacks = upChildPacks.OrderBy(pack=>nodeChildren_sortValues[pack.origIndex]);
			downChildPacks = downChildPacks.OrderByDescending(pack=>nodeChildren_sortValues[pack.origIndex]);
			ApplyOrderPostProcessingForChildPacks(upChildPacks);
			ApplyOrderPostProcessingForChildPacks(downChildPacks);
		} else {
			childPacks = childPacks.OrderByDescending(pack=>nodeChildren_sortValues[pack.origIndex]);
			ApplyOrderPostProcessingForChildPacks(childPacks);
		}
		function ApplyOrderPostProcessingForChildPacks(packs) {
			for (let pack of packs) {
				if (pack.node.chainAfter == "[start]") {
					packs.Remove(pack);
					packs.Insert(0, pack); 
				}
				let chainAfterNode = nodeChildren.FirstOrX(a=>a._id.toString() == pack.node.chainAfter);
				if (chainAfterNode) {
					packs.Remove(pack);
					let chainAfterNode_index = packs.findIndex(a=>a.node == chainAfterNode);
					packs.Insert(chainAfterNode_index + 1, pack); 
				}
			}
			let metaThesisPack = packs.FirstOrX(a=>a.node.metaThesis);
			if (metaThesisPack) {
				packs.Remove(metaThesisPack);
				packs.Insert(0, metaThesisPack); 
			}
		}

		//let {width, expectedHeight} = this.GetMeasurementInfo(this.props, this.state);
		let {width, expectedHeight} = this.GetMeasurementInfo();
		let innerBoxOffset = ((childrenCenterY|0) - (expectedHeight / 2)).KeepAtLeast(0);

		this.childBoxes = [];
		return (
			<div className="NodeUI clickThrough" style={{position: "relative", display: "flex", alignItems: "flex-start", padding: "5px 0", opacity: widthOverride != 0 ? 1 : 0}}>
				<div ref="innerBoxHolder" className="innerBoxHolder clickThrough" style={E(
					//{position: "relative"},
					/*useAutoOffset && {display: "flex", height: "100%", flexDirection: "column", justifyContent: "center"},
					!useAutoOffset && {paddingTop: innerBoxOffset},*/
					{paddingTop: innerBoxOffset}
				)}>
					<NodeUI_Inner ref="innerBox" map={map} node={node} nodeView={nodeView} path={path} width={width} widthOverride={widthOverride}/>
					{/*<NodeUI_Inner ref="innerBox" {...{map, node: nodeWithFinalType, nodeView, path, width}} widthOverride={widthOverride}/>*/}
					{IsArgumentNode(node) && nodeChildren.length > 0 && nodeChildren.length < 3 &&
						<Div ct style={{
							//whiteSpace: "normal", position: "absolute", left: 0, right: 0, top: "100%", fontSize: 12
							marginTop: 5, fontSize: 12
						}}>
							Needs 2 premises to be visible.
						</Div>}
				</div>
				{nodeChildren == childrenPlaceholder &&
					<div style={{margin: "auto 0 auto 10px"}}>...</div>}
				{nodeChildren != childrenPlaceholder && !expanded && nodeChildren.length != 0 &&
					<div style={{margin: "auto 0 auto 7px", fontSize: 12, color: "rgba(255,255,255,.5)"}}>{nodeChildren.length}</div>}
				{hasBeenExpanded && !separateChildren &&
					<div ref="childHolder" className="childHolder clickThrough" style={{
						display: expanded ? "flex" : "none", flexDirection: "column", marginLeft: 30,
						//display: "flex", flexDirection: "column", marginLeft: 10, maxHeight: expanded ? 500 : 0, transition: "max-height 1s", overflow: "hidden",
					}}>
						{svgInfo.mainBoxOffset &&
							<NodeConnectorBackground node={node} mainBoxOffset={svgInfo.mainBoxOffset} shouldUpdate={this.lastRender_source == RenderSource.SetState}
								childNodes={nodeChildren} childBoxOffsets={svgInfo.oldChildBoxOffsets}/>}
						{childPacks.map(a=>a.ui)}
					</div>}<commit_msg>* Fixed that link-lines would have gap on left.<commit_after>import {BaseComponent, Div, Span, Instant, FindDOM, SimpleShouldUpdate, BaseProps, GetInnerComp, ShallowCompare, RenderSource, FindDOM_, ShallowEquals} from "../../../../Frame/UI/ReactGlobals";
import {connect} from "react-redux";
import {DBPath, GetData} from "../../../../Frame/Database/DatabaseHelpers";
import {Debugger, QuickIncrement, E, GetTimeSinceLoad} from "../../../../Frame/General/Globals_Free";
import Button from "../../../../Frame/ReactComponents/Button";
import {PropTypes, Component} from "react";
import Action from "../../../../Frame/General/Action";
import {Log} from "../../../../Frame/General/Logging";
import {WaitXThenRun} from "../../../../Frame/General/Timers";
import V from "../../../../Frame/V/V";
import * as VMenuTest1 from "react-vmenu";
import VMenu, {VMenuItem} from "react-vmenu";
import Select from "../../../../Frame/ReactComponents/Select";
import {GetEntries} from "../../../../Frame/General/Enums";
import {ShowMessageBox} from "../../../../Frame/UI/VMessageBox";
import TextInput from "../../../../Frame/ReactComponents/TextInput";
import {DN, ToJSON} from "../../../../Frame/General/Globals";
import {DataSnapshot} from "firebase";
import {styles} from "../../../../Frame/UI/GlobalStyles";
import {createSelector} from "reselect";
import NodeUI_Inner from "./NodeUI_Inner";
import {createMarkupForStyles} from "react-dom/lib/CSSPropertyOperations";
import NodeConnectorBackground from "./NodeConnectorBackground";
import {Vector2i} from "../../../../Frame/General/VectorStructs";
import {CachedTransform, CombineDynamicPropMaps} from "../../../../Frame/V/VCache";
import {RootState} from "../../../../Store/index";
import {GetNodeView} from "../../../../Store/main/mapViews";
import {MapNode, ThesisForm, MapNodeEnhanced} from "../../../../Store/firebase/nodes/@MapNode";
import {Map} from "../../../../Store/firebase/maps/@Map";
import {GetNodeChildren, GetParentNode, GetNodeChildrenEnhanced} from "../../../../Store/firebase/nodes";
import {MapNodeView} from "../../../../Store/main/mapViews/@MapViews";
import {MapNodeType, MapNodeType_Info} from "../../../../Store/firebase/nodes/@MapNodeType";
import {Connect} from "../../../../Frame/Database/FirebaseConnect";
import {GetFillPercentForRatingAverage, GetRatingAverage} from "../../../../Store/firebase/nodeRatings";
import Column from "../../../../Frame/ReactComponents/Column";
import { GetRatingTypesForNode, GetNodeDisplayText, GetFontSizeForNode, GetNodeForm, GetFinalNodeTypeAtPath, GetMainRatingType, GetNodeEnhanced, GetSortByRatingType, IsArgumentNode } from "../../../../Store/firebase/nodes/$node";
import * as FastDOM from "fastdom";

// modified version which only requests paths that do not yet exist in the store
/*export function Firebase_Connect(innerFirebaseConnect) {
	return firebaseConnect(props=> {
		let firebase = State().firebase;

		let innerPaths = innerFirebaseConnect(props) as string[];
		// if inner-paths are all already loaded, don't request the paths this time
		let innerPaths_unrequested = innerPaths.Where(path=>GetData(firebase, path) == null);
		/*Log(innerPaths.length + ";" + innerPaths_unrequested.length + "\n" + innerPaths + "\n" + innerPaths_unrequested);
		if (GetTimeSinceLoad() > 5)
			debugger;*#/
		return innerPaths_unrequested;
	});
}*/

let childrenPlaceholder = [];

type Props = {map: Map, node: MapNodeEnhanced, path?: string, widthOverride?: number, onHeightOrPosChange?: ()=>void}
	& Partial<{form: ThesisForm, nodeView: MapNodeView,
		nodeChildren: MapNodeEnhanced[],
		//nodeChildren_fillPercents: number[],
		nodeChildren_sortValues: number[],
	}>;
type State = {hasBeenExpanded: boolean, childrenWidthOverride: number, childrenCenterY: number, svgInfo: {mainBoxOffset: Vector2i, oldChildBoxOffsets: Vector2i[]}};
@Connect((state: RootState, {node, path, map}: Props & BaseProps)=> {
	//Log("Calling NodeUI connect func.");
	let nodeView = GetNodeView(map._id, path) || new MapNodeView();

	let nodeChildren = GetNodeChildrenEnhanced(node, path);
	// only pass nodeChildren when all are loaded
	nodeChildren = nodeChildren.Any(a=>a == null) ? childrenPlaceholder : nodeChildren;
	/*let nodeChildren_finalTypes = nodeChildren == childrenPlaceholder ? childrenPlaceholder : nodeChildren.map(child=> {
		return GetFinalNodeTypeAtPath(child, path + "/" + child._id);
	});*/

	let nodeChildren_sortValues = nodeChildren == childrenPlaceholder ? childrenPlaceholder : nodeChildren.map(child=> {
		return GetFillPercentForRatingAverage(child, GetRatingAverage(child._id, GetSortByRatingType(child)), GetNodeForm(child) == ThesisForm.Negation);
	});
	/*for (var i = 0; i < nodeChildren.length; i++) {
		let child = nodeChildren[i];
		if (child.chainAfter == "[start]") {
			nodeChildren_sortValues[i] = -1;
			continue;
		}
		let chainAfterNode = nodeChildren.FirstOrX(a=>a._id.toString() == child.chainAfter);
		if (chainAfterNode) {
			let chainAfterNode_sortValue = nodeChildren_sortValues[nodeChildren.indexOf(chainAfterNode)];
			nodeChildren_sortValues[i] = chainAfterNode_sortValue + .000001;
		}
	}*/
	let nodeChildren_fillPercents = nodeChildren == childrenPlaceholder ? childrenPlaceholder : nodeChildren.map(child=> {
		return GetFillPercentForRatingAverage(child, GetRatingAverage(child._id, GetMainRatingType(child)), GetNodeForm(child) == ThesisForm.Negation);
	});
	
	return {
		path: path || node._id.toString(),

		//node_finalType: GetFinalNodeTypeAtPath(node, path),
		//nodeEnhanced: GetNodeEnhanced(node, path),
		form: GetNodeForm(node, GetParentNode(path)),
		// only pass new nodeView when its local-props are different
		nodeView: CachedTransform("nodeView_transform1", [map._id, path], nodeView.Excluding("focus", "viewOffset", "children"), ()=>nodeView),
		/*nodeChildren: CachedTransform("nodeChildren_transform1", {path}, CombineDynamicPropMaps(nodeChildren, nodeChildren_finalTypes),
			()=>nodeChildren.map((child, index)=> {
				return child.Extended({finalType: nodeChildren_finalTypes[index]});
			})),*/
		nodeChildren,
		nodeChildren_sortValues: CachedTransform("nodeChildren_sortValues_transform1", [node._id], nodeChildren_sortValues, ()=>nodeChildren_sortValues),
		nodeChildren_fillPercents: CachedTransform("nodeChildren_fillPercents_transform1", [node._id], nodeChildren_fillPercents, ()=>nodeChildren_fillPercents),
	};
})
export default class NodeUI extends BaseComponent<Props, State> {
	static renderCount = 0;
	static lastRenderTime = -1;
	
	constructor(props) {
		super(props);
		this.state = {svgInfo: {}} as any;
	}
	ComponentWillMountOrReceiveProps(newProps) {
		let {nodeView} = newProps;
		if (nodeView && nodeView.expanded)
			this.SetState({hasBeenExpanded: true});
	}

	/*shouldComponentUpdate(nextProps, nextState) {
		debugger;
		return true;
	}*/

	render() {
		let {map, node, path, form, widthOverride, children, nodeView, nodeChildren, nodeChildren_sortValues} = this.props;
		let expanded = nodeView && nodeView.expanded;
		let {hasBeenExpanded, childrenWidthOverride, childrenCenterY, svgInfo} = this.state;
		//Log(`Updating NodeUI (${RenderSource[this.lastRender_source]}):${node._id};PropsChanged:${this.GetPropsChanged()};StateChanged:${this.GetStateChanged()}`);
		NodeUI.renderCount++;
		NodeUI.lastRenderTime = Date.now();

		let separateChildren = node.finalType == MapNodeType.Thesis;
		type ChildPack = {origIndex: number, node: MapNodeEnhanced, ui: JSX.Element};
		let childPacks: ChildPack[] = nodeChildren.map((child, index)=> {
			return {
				origIndex: index,
				node: child,
				ui: <NodeUI key={index} ref={c=>this.childBoxes[index] = c} map={map} node={child}
					path={path + "/" + child._id} widthOverride={childrenWidthOverride} onHeightOrPosChange={this.OnChildHeightOrPosChange}/>
			};
		});
		let upChildPacks = separateChildren ? childPacks.filter(a=>a.node.finalType == MapNodeType.SupportingArgument) : [];
		let downChildPacks = separateChildren ? childPacks.filter(a=>a.node.finalType == MapNodeType.OpposingArgument) : [];

		// apply sorting
		if (separateChildren) {
			upChildPacks = upChildPacks.OrderBy(pack=>nodeChildren_sortValues[pack.origIndex]);
			downChildPacks = downChildPacks.OrderByDescending(pack=>nodeChildren_sortValues[pack.origIndex]);
			ApplyOrderPostProcessingForChildPacks(upChildPacks);
			ApplyOrderPostProcessingForChildPacks(downChildPacks);
		} else {
			childPacks = childPacks.OrderByDescending(pack=>nodeChildren_sortValues[pack.origIndex]);
			ApplyOrderPostProcessingForChildPacks(childPacks);
		}
		function ApplyOrderPostProcessingForChildPacks(packs) {
			for (let pack of packs) {
				if (pack.node.chainAfter == "[start]") {
					packs.Remove(pack);
					packs.Insert(0, pack); 
				}
				let chainAfterNode = nodeChildren.FirstOrX(a=>a._id.toString() == pack.node.chainAfter);
				if (chainAfterNode) {
					packs.Remove(pack);
					let chainAfterNode_index = packs.findIndex(a=>a.node == chainAfterNode);
					packs.Insert(chainAfterNode_index + 1, pack); 
				}
			}
			let metaThesisPack = packs.FirstOrX(a=>a.node.metaThesis);
			if (metaThesisPack) {
				packs.Remove(metaThesisPack);
				packs.Insert(0, metaThesisPack); 
			}
		}

		//let {width, expectedHeight} = this.GetMeasurementInfo(this.props, this.state);
		let {width, expectedHeight} = this.GetMeasurementInfo();
		let innerBoxOffset = ((childrenCenterY|0) - (expectedHeight / 2)).KeepAtLeast(0);

		this.childBoxes = [];
		return (
			<div className="NodeUI clickThrough" style={{position: "relative", display: "flex", alignItems: "flex-start", padding: "5px 0", opacity: widthOverride != 0 ? 1 : 0}}>
				<div ref="innerBoxHolder" className="innerBoxHolder clickThrough" style={E(
					//{position: "relative"},
					/*useAutoOffset && {display: "flex", height: "100%", flexDirection: "column", justifyContent: "center"},
					!useAutoOffset && {paddingTop: innerBoxOffset},*/
					{paddingTop: innerBoxOffset}
				)}>
					<NodeUI_Inner ref="innerBox" map={map} node={node} nodeView={nodeView} path={path} width={width} widthOverride={widthOverride}/>
					{/*<NodeUI_Inner ref="innerBox" {...{map, node: nodeWithFinalType, nodeView, path, width}} widthOverride={widthOverride}/>*/}
					{IsArgumentNode(node) && nodeChildren.length > 0 && nodeChildren.length < 3 &&
						<Div ct style={{
							//whiteSpace: "normal", position: "absolute", left: 0, right: 0, top: "100%", fontSize: 12
							marginTop: 5, fontSize: 12,
							width: 0, // fixes that link-lines would have gap on left
						}}>
							Needs 2 premises to be visible.
						</Div>}
				</div>
				{nodeChildren == childrenPlaceholder &&
					<div style={{margin: "auto 0 auto 10px"}}>...</div>}
				{nodeChildren != childrenPlaceholder && !expanded && nodeChildren.length != 0 &&
					<div style={{margin: "auto 0 auto 7px", fontSize: 12, color: "rgba(255,255,255,.5)"}}>{nodeChildren.length}</div>}
				{hasBeenExpanded && !separateChildren &&
					<div ref="childHolder" className="childHolder clickThrough" style={{
						display: expanded ? "flex" : "none", flexDirection: "column", marginLeft: 30,
						//display: "flex", flexDirection: "column", marginLeft: 10, maxHeight: expanded ? 500 : 0, transition: "max-height 1s", overflow: "hidden",
					}}>
						{svgInfo.mainBoxOffset &&
							<NodeConnectorBackground node={node} mainBoxOffset={svgInfo.mainBoxOffset} shouldUpdate={this.lastRender_source == RenderSource.SetState}
								childNodes={nodeChildren} childBoxOffsets={svgInfo.oldChildBoxOffsets}/>}
						{childPacks.map(a=>a.ui)}
					</div>}
{'fraction_non_alphanumeric': 0.16149365327769083, 'fraction_numerical': 0.00639019300991132, 'mean_word_length': 4.829954384186518, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5616412', 'n_tokens_mistral': 7696, 'n_tokens_neox': 7009, 'n_words': 1499}