diff --git a/src/components/AstExplorer.tsx b/src/components/AstExplorer.tsx new file mode 100644 index 000000000..57d0b19e0 --- /dev/null +++ b/src/components/AstExplorer.tsx @@ -0,0 +1,182 @@ +import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst' +import { useEffect, useRef, useState } from 'react' +import { useStore } from 'useStore' + +export function AstExplorer() { + const { ast, setHighlightRange, selectionRanges } = useStore((s) => ({ + ast: s.ast, + setHighlightRange: s.setHighlightRange, + selectionRanges: s.selectionRanges, + })) + const pathToNode = getNodePathFromSourceRange( + ast, + selectionRanges.codeBasedSelections?.[0]?.range + ) + const node = getNodeFromPath(ast, pathToNode).node + const [filterKeys, setFilterKeys] = useState(['start', 'end']) + + return ( +
+
+ filter out keys:
+ {['start', 'end', 'type'].map((key) => { + return ( + + ) + })} +
+
{ + setHighlightRange([0, 0]) + }} + > +
+          
+        
+
+
+ ) +} + +function DisplayBody({ + body, + filterKeys, + node, +}: { + body: { start: number; end: number; [key: string]: any }[] + filterKeys: string[] + node: any +}) { + return ( + <> + {body.map((b, index) => { + return ( +
+ +
+ ) + })} + + ) +} + +function DisplayObj({ + obj, + filterKeys, + node, +}: { + obj: { start: number; end: number; [key: string]: any } + filterKeys: string[] + node: any +}) { + const { setHighlightRange, setCursor2 } = useStore((s) => ({ + setHighlightRange: s.setHighlightRange, + setCursor2: s.setCursor2, + })) + const ref = useRef(null) + const [hasCursor, setHasCursor] = useState(false) + const [isCollapsed, setIsCollapsed] = useState(false) + useEffect(() => { + if ( + node?.start === obj?.start && + node?.end === obj?.end && + node.type === obj?.type + ) { + ref?.current?.scrollIntoView?.({ behavior: 'smooth', block: 'center' }) + setHasCursor(true) + } else { + setHasCursor(false) + } + }, [node.start, node.end, node.type]) + return ( +
 {
+        setHighlightRange([obj?.start || 0, obj.end])
+        e.stopPropagation()
+      }}
+      onMouseMove={(e) => {
+        e.stopPropagation()
+        setHighlightRange([obj?.start || 0, obj.end])
+      }}
+      onClick={(e) => {
+        setCursor2({ type: 'default', range: [obj?.start || 0, obj.end || 0] })
+        e.stopPropagation()
+      }}
+    >
+      {isCollapsed ? (
+        
+      ) : (
+        
+          {/*  */}
+          
    + {Object.entries(obj).map(([key, value]) => { + if (filterKeys.includes(key)) { + return null + } else if (Array.isArray(value)) { + return ( +
  • + {`${key}: [`} + + {']'} +
  • + ) + } else if ( + typeof value === 'object' && + value !== null && + value?.end + ) { + return ( +
  • + {key}: + +
  • + ) + } else if ( + typeof value === 'string' || + typeof value === 'number' + ) { + return ( +
  • + {key}: {value} +
  • + ) + } + })} +
+
+ )} +
+ ) +} diff --git a/src/components/DebugPanel.tsx b/src/components/DebugPanel.tsx index a71a9832f..d58f61be9 100644 --- a/src/components/DebugPanel.tsx +++ b/src/components/DebugPanel.tsx @@ -6,6 +6,7 @@ import { useState } from 'react' import { ActionButton } from '../components/ActionButton' import { faCheck } from '@fortawesome/free-solid-svg-icons' import { isReducedMotion } from 'lang/util' +import { AstExplorer } from './AstExplorer' type SketchModeCmd = Extract< Extract['cmd'], @@ -94,6 +95,9 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => { > Send sketch mode command +
+ +
)