Add support for highlighting when hovering over a node.
This commit is contained in:
parent
e89be0feff
commit
0e02e09018
@ -2,7 +2,7 @@ import React, { ReactNode, useState } from "react";
|
|||||||
import "./Editor.css";
|
import "./Editor.css";
|
||||||
import { Highlight } from "./highlight";
|
import { Highlight } from "./highlight";
|
||||||
import { buildShadow } from "./shadow";
|
import { buildShadow } from "./shadow";
|
||||||
import OrgAst from "./OrgAst";
|
import OrgAst, { OrgNodeReference } from "./OrgAst";
|
||||||
import { parse_org } from "../../organic/target/wasm32-unknown-unknown/js/wasm";
|
import { parse_org } from "../../organic/target/wasm32-unknown-unknown/js/wasm";
|
||||||
|
|
||||||
const default_org_source: string = `Welcome to the Organic Wasm Demo!
|
const default_org_source: string = `Welcome to the Organic Wasm Demo!
|
||||||
@ -31,8 +31,15 @@ function Editor({ defaultValue = default_org_source }) {
|
|||||||
|
|
||||||
const [highlights, setHighlights] = useState<Array<Highlight>>([]);
|
const [highlights, setHighlights] = useState<Array<Highlight>>([]);
|
||||||
|
|
||||||
function setHighlight(start: number, end: number) {
|
function setHighlight(nodes: OrgNodeReference[]) {
|
||||||
let new_highlights = [new Highlight(start, end)];
|
let new_highlights = nodes.map((node: OrgNodeReference) => {
|
||||||
|
return new Highlight(node.start - 1, node.end - 1);
|
||||||
|
});
|
||||||
|
new_highlights.sort(function (a, b) {
|
||||||
|
if (a.start < b.start) return -1;
|
||||||
|
if (a.start > b.start) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
setHighlights(new_highlights);
|
setHighlights(new_highlights);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.OrgAstNode.hovered:not(.selected) {
|
||||||
|
> .OrgAstNodeType {
|
||||||
|
background: #70f8ba;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.OrgAstNodeType {
|
.OrgAstNodeType {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
1
src/OrgAst.module.css.d.ts
vendored
1
src/OrgAst.module.css.d.ts
vendored
@ -3,5 +3,6 @@ export const OrgAstNode: string;
|
|||||||
export const OrgAstNodeType: string;
|
export const OrgAstNodeType: string;
|
||||||
export const OrgAstChildren: string;
|
export const OrgAstChildren: string;
|
||||||
export const selected: string;
|
export const selected: string;
|
||||||
|
export const hovered: string;
|
||||||
export const OrgAstProperties: string;
|
export const OrgAstProperties: string;
|
||||||
export const OrgAstObjectTree: string;
|
export const OrgAstObjectTree: string;
|
||||||
|
111
src/OrgAst.tsx
111
src/OrgAst.tsx
@ -8,11 +8,28 @@ const OrgAst = (props: {
|
|||||||
astTree: any;
|
astTree: any;
|
||||||
value: string;
|
value: string;
|
||||||
}) => {
|
}) => {
|
||||||
const [selectedNode, setSelectedNode] = useState<string>("");
|
const [selectedNode, setSelectedNode] = useState<OrgNodeReference | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const [hoveredNode, setHoveredNode] = useState<OrgNodeReference | null>(null);
|
||||||
|
|
||||||
function selectNode(uid: string, start: number, end: number) {
|
function selectNode(uid: string, start: number, end: number) {
|
||||||
props.setHighlight(start, end);
|
const new_node: OrgNodeReference = { uid: uid, start: start, end: end };
|
||||||
setSelectedNode(uid);
|
props.setHighlight([new_node, hoveredNode].filter((node) => node !== null));
|
||||||
|
setSelectedNode({ uid: uid, start: start, end: end });
|
||||||
|
}
|
||||||
|
|
||||||
|
function startHoverNode(uid: string, start: number, end: number) {
|
||||||
|
const new_node: OrgNodeReference = { uid: uid, start: start, end: end };
|
||||||
|
props.setHighlight(
|
||||||
|
[selectedNode, new_node].filter((node) => node !== null),
|
||||||
|
);
|
||||||
|
setHoveredNode({ uid: uid, start: start, end: end });
|
||||||
|
}
|
||||||
|
|
||||||
|
function endHoverNode(uid: string) {
|
||||||
|
props.setHighlight([selectedNode].filter((node) => node !== null));
|
||||||
|
setHoveredNode(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.astTree.status !== "success") {
|
if (props.astTree.status !== "success") {
|
||||||
@ -24,6 +41,8 @@ const OrgAst = (props: {
|
|||||||
key="^"
|
key="^"
|
||||||
uid="^"
|
uid="^"
|
||||||
selectNode={selectNode}
|
selectNode={selectNode}
|
||||||
|
startHoverNode={startHoverNode}
|
||||||
|
endHoverNode={endHoverNode}
|
||||||
node={props.astTree.content}
|
node={props.astTree.content}
|
||||||
selectedNode={selectedNode}
|
selectedNode={selectedNode}
|
||||||
/>
|
/>
|
||||||
@ -32,34 +51,68 @@ const OrgAst = (props: {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface OrgNodeReference {
|
||||||
|
uid: string;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
}
|
||||||
|
|
||||||
const OrgAstNode = (props: {
|
const OrgAstNode = (props: {
|
||||||
selectNode: Function;
|
selectNode: Function;
|
||||||
|
startHoverNode: Function;
|
||||||
|
endHoverNode: Function;
|
||||||
node: any;
|
node: any;
|
||||||
uid: string;
|
uid: string;
|
||||||
selectedNode: string;
|
selectedNode: OrgNodeReference | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
function selectNode() {
|
function selectNode() {
|
||||||
props.selectNode(
|
props.selectNode(
|
||||||
props.uid,
|
props.uid,
|
||||||
props.node["standard-properties"]["begin"] - 1,
|
props.node["standard-properties"]["begin"],
|
||||||
props.node["standard-properties"]["end"] - 1,
|
props.node["standard-properties"]["end"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodeClassName =
|
function hoverNode() {
|
||||||
props.selectedNode === props.uid
|
props.startHoverNode(
|
||||||
? styles.OrgAstNode + " " + styles.selected
|
props.uid,
|
||||||
: styles.OrgAstNode;
|
props.node["standard-properties"]["begin"],
|
||||||
|
props.node["standard-properties"]["end"],
|
||||||
|
);
|
||||||
|
setIsHovered(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function endHoverNode() {
|
||||||
|
props.endHoverNode(props.uid);
|
||||||
|
setIsHovered(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
let nodeClassName = styles.OrgAstNode;
|
||||||
|
if (props.selectedNode?.uid === props.uid) {
|
||||||
|
nodeClassName = nodeClassName + " " + styles.selected;
|
||||||
|
}
|
||||||
|
if (isHovered) {
|
||||||
|
nodeClassName = nodeClassName + " " + styles.hovered;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={nodeClassName}>
|
<div className={nodeClassName}>
|
||||||
<div className={styles.OrgAstNodeType} onClick={selectNode}>
|
<div
|
||||||
|
className={styles.OrgAstNodeType}
|
||||||
|
onClick={selectNode}
|
||||||
|
onMouseEnter={hoverNode}
|
||||||
|
onMouseLeave={endHoverNode}
|
||||||
|
>
|
||||||
{props.node["ast-node"]}
|
{props.node["ast-node"]}
|
||||||
</div>
|
</div>
|
||||||
<details>
|
<details>
|
||||||
<summary>Standard Properties</summary>
|
<summary>Standard Properties</summary>
|
||||||
<OrgPropertiesList
|
<OrgPropertiesList
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
parentUniqueId={props.uid}
|
parentUniqueId={props.uid}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
properties={props.node["standard-properties"]}
|
properties={props.node["standard-properties"]}
|
||||||
@ -71,6 +124,8 @@ const OrgAstNode = (props: {
|
|||||||
<summary>Properties</summary>
|
<summary>Properties</summary>
|
||||||
<OrgPropertiesList
|
<OrgPropertiesList
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
parentUniqueId={props.uid}
|
parentUniqueId={props.uid}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
properties={props.node.properties}
|
properties={props.node.properties}
|
||||||
@ -84,6 +139,8 @@ const OrgAstNode = (props: {
|
|||||||
<div className={styles.OrgAstChildren}>
|
<div className={styles.OrgAstChildren}>
|
||||||
<OrgAstNodeList
|
<OrgAstNodeList
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
parentUniqueId={props.uid}
|
parentUniqueId={props.uid}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
node_list={props.node.children}
|
node_list={props.node.children}
|
||||||
@ -97,8 +154,10 @@ const OrgAstNode = (props: {
|
|||||||
|
|
||||||
const OrgAstNodeList = (props: {
|
const OrgAstNodeList = (props: {
|
||||||
selectNode: Function;
|
selectNode: Function;
|
||||||
|
startHoverNode: Function;
|
||||||
|
endHoverNode: Function;
|
||||||
parentUniqueId: string;
|
parentUniqueId: string;
|
||||||
selectedNode: string;
|
selectedNode: OrgNodeReference | null;
|
||||||
node_list: any[];
|
node_list: any[];
|
||||||
}): React.JSX.Element[] => {
|
}): React.JSX.Element[] => {
|
||||||
return props.node_list.map((node) => {
|
return props.node_list.map((node) => {
|
||||||
@ -116,6 +175,8 @@ const OrgAstNodeList = (props: {
|
|||||||
key={uid}
|
key={uid}
|
||||||
uid={uid}
|
uid={uid}
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
node={node}
|
node={node}
|
||||||
/>
|
/>
|
||||||
@ -125,8 +186,10 @@ const OrgAstNodeList = (props: {
|
|||||||
|
|
||||||
const OrgPropertiesList = (props: {
|
const OrgPropertiesList = (props: {
|
||||||
selectNode: Function;
|
selectNode: Function;
|
||||||
|
startHoverNode: Function;
|
||||||
|
endHoverNode: Function;
|
||||||
parentUniqueId: string;
|
parentUniqueId: string;
|
||||||
selectedNode: string;
|
selectedNode: OrgNodeReference | null;
|
||||||
properties: Object;
|
properties: Object;
|
||||||
}): React.JSX.Element => {
|
}): React.JSX.Element => {
|
||||||
const entries = Object.entries(props.properties)
|
const entries = Object.entries(props.properties)
|
||||||
@ -150,6 +213,8 @@ const OrgPropertiesList = (props: {
|
|||||||
<td>
|
<td>
|
||||||
<OrgPropertyValue
|
<OrgPropertyValue
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
parentUniqueId={props.parentUniqueId}
|
parentUniqueId={props.parentUniqueId}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
value={value}
|
value={value}
|
||||||
@ -168,8 +233,10 @@ const OrgPropertiesList = (props: {
|
|||||||
|
|
||||||
const OrgPropertyValue = (props: {
|
const OrgPropertyValue = (props: {
|
||||||
selectNode: Function;
|
selectNode: Function;
|
||||||
|
startHoverNode: Function;
|
||||||
|
endHoverNode: Function;
|
||||||
parentUniqueId: string;
|
parentUniqueId: string;
|
||||||
selectedNode: string;
|
selectedNode: OrgNodeReference | null;
|
||||||
value: any;
|
value: any;
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
if (
|
if (
|
||||||
@ -183,6 +250,8 @@ const OrgPropertyValue = (props: {
|
|||||||
<div className={styles.OrgAstChildren}>
|
<div className={styles.OrgAstChildren}>
|
||||||
<OrgAstNodeList
|
<OrgAstNodeList
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
parentUniqueId={props.parentUniqueId}
|
parentUniqueId={props.parentUniqueId}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
node_list={props.value}
|
node_list={props.value}
|
||||||
@ -193,6 +262,8 @@ const OrgPropertyValue = (props: {
|
|||||||
return (
|
return (
|
||||||
<OrgObjectTree
|
<OrgObjectTree
|
||||||
selectNode={props.selectNode}
|
selectNode={props.selectNode}
|
||||||
|
startHoverNode={props.startHoverNode}
|
||||||
|
endHoverNode={props.endHoverNode}
|
||||||
parentUniqueId={props.parentUniqueId}
|
parentUniqueId={props.parentUniqueId}
|
||||||
selectedNode={props.selectedNode}
|
selectedNode={props.selectedNode}
|
||||||
value={props.value}
|
value={props.value}
|
||||||
@ -205,13 +276,17 @@ const OrgPropertyValue = (props: {
|
|||||||
|
|
||||||
interface OrgObjectTreeProps {
|
interface OrgObjectTreeProps {
|
||||||
selectNode: Function;
|
selectNode: Function;
|
||||||
|
startHoverNode: Function;
|
||||||
|
endHoverNode: Function;
|
||||||
parentUniqueId: string;
|
parentUniqueId: string;
|
||||||
selectedNode: string;
|
selectedNode: OrgNodeReference | null;
|
||||||
value: any;
|
value: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
function OrgObjectTree({
|
function OrgObjectTree({
|
||||||
selectNode,
|
selectNode,
|
||||||
|
startHoverNode,
|
||||||
|
endHoverNode,
|
||||||
parentUniqueId,
|
parentUniqueId,
|
||||||
selectedNode,
|
selectedNode,
|
||||||
value,
|
value,
|
||||||
@ -224,6 +299,8 @@ function OrgObjectTree({
|
|||||||
<td>
|
<td>
|
||||||
<OrgAstNodeList
|
<OrgAstNodeList
|
||||||
selectNode={selectNode}
|
selectNode={selectNode}
|
||||||
|
startHoverNode={startHoverNode}
|
||||||
|
endHoverNode={endHoverNode}
|
||||||
parentUniqueId={parentUniqueId}
|
parentUniqueId={parentUniqueId}
|
||||||
selectedNode={selectedNode}
|
selectedNode={selectedNode}
|
||||||
node_list={entry[0]}
|
node_list={entry[0]}
|
||||||
@ -235,6 +312,8 @@ function OrgObjectTree({
|
|||||||
<td>
|
<td>
|
||||||
<OrgAstNodeList
|
<OrgAstNodeList
|
||||||
selectNode={selectNode}
|
selectNode={selectNode}
|
||||||
|
startHoverNode={startHoverNode}
|
||||||
|
endHoverNode={endHoverNode}
|
||||||
parentUniqueId={parentUniqueId}
|
parentUniqueId={parentUniqueId}
|
||||||
selectedNode={selectedNode}
|
selectedNode={selectedNode}
|
||||||
node_list={entry[1]}
|
node_list={entry[1]}
|
||||||
@ -275,4 +354,4 @@ function is_object_tree(val: any): boolean {
|
|||||||
return is_object(val) && val.hasOwnProperty("object-tree");
|
return is_object(val) && val.hasOwnProperty("object-tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OrgAst;
|
export { OrgAst as default, OrgNodeReference };
|
||||||
|
Loading…
Reference in New Issue
Block a user