From 1545d377725f0076ca885b00ad582b2b68722cb9 Mon Sep 17 00:00:00 2001 From: Ritabrata Ghosh <76sonali40@gmail.com> Date: Wed, 4 Feb 2026 15:18:48 +0530 Subject: [PATCH 1/3] metaschema errors chain ui Signed-off-by: Ritabrata Ghosh <76sonali40@gmail.com> --- webview/src/components/MetaschemaChain.tsx | 143 +++++++++++++++++++++ webview/src/components/MetaschemaTab.tsx | 57 +------- webview/src/utils/splitIntoRows.ts | 18 +++ 3 files changed, 166 insertions(+), 52 deletions(-) create mode 100644 webview/src/components/MetaschemaChain.tsx create mode 100644 webview/src/utils/splitIntoRows.ts diff --git a/webview/src/components/MetaschemaChain.tsx b/webview/src/components/MetaschemaChain.tsx new file mode 100644 index 0000000..4e69114 --- /dev/null +++ b/webview/src/components/MetaschemaChain.tsx @@ -0,0 +1,143 @@ +import { useEffect, useRef, useState } from 'react'; +import type { MetaschemaError, Position } from '../../../protocol/types'; +import { goToPosition } from '../message'; + +const BOX_WIDTH = 260; +const GAP = 12; + +interface Props { + errors: MetaschemaError[]; +} + +export function MetaschemaChain({ errors }: Props) { + const containerRef = useRef(null); + const [rows, setRows] = useState([]); + const [rowWidth, setRowWidth] = useState(0); + + useEffect(() => { + if (!containerRef.current) return; + + const compute = () => { + const width = containerRef.current!.clientWidth; + if (width < BOX_WIDTH) { + setRows(errors.map(e => [e])); + setRowWidth(BOX_WIDTH); + return; + } + + const perRow = Math.max( + 1, + Math.floor((width + GAP) / (BOX_WIDTH + GAP)) + ); + + const computedRowWidth = perRow * (BOX_WIDTH + GAP) - GAP; + + const newRows: MetaschemaError[][] = []; + for (let i = 0; i < errors.length; i += perRow) { + newRows.push(errors.slice(i, i + perRow)); + } + + setRows(newRows); + setRowWidth(computedRowWidth); + }; + compute(); + + const observer = new ResizeObserver(compute); + observer.observe(containerRef.current); + + return () => observer.disconnect(); + }, [errors]); + + return ( +
+
+ {rows.map((row, rowIndex) => { + const isLTR = rowIndex % 2 === 0; + const items = isLTR ? row : [...row].reverse(); + + return ( +
+ {/* ROW */} +
+ {items.map((error, index) => ( +
+ + + {/* Horizontal arrows */} + {index < items.length - 1 && + (isLTR ? : )} +
+ ))} +
+ + {/* TURN ARROW */} + {rowIndex < rows.length - 1 && ( +
+
+ +
+
+ )} +
+ ); + })} +
+
+ ); +} + +function ErrorBox({ error }: { error: MetaschemaError }) { + return ( +
+ error.instancePosition && + goToPosition(error.instancePosition as Position) + } + > +
+ {error.error} +
+ + {error.instanceLocation && ( +
+ {error.instanceLocation || '(root)'} +
+ )} +
+ ); +} + +function ArrowRight() { + return ; +} + +function ArrowLeft() { + return ; +} + +function ArrowDown() { + return ( +
+ ↓ +
+ ); +} diff --git a/webview/src/components/MetaschemaTab.tsx b/webview/src/components/MetaschemaTab.tsx index 224c075..276f133 100644 --- a/webview/src/components/MetaschemaTab.tsx +++ b/webview/src/components/MetaschemaTab.tsx @@ -2,6 +2,7 @@ import type { MetaschemaResult, MetaschemaError, Position } from '../../../proto import { goToPosition } from '../message'; import { RawOutput } from './RawOutput'; import { CheckCircle, AlertTriangle, FileQuestion } from 'lucide-react'; +import { MetaschemaChain } from './MetaschemaChain'; export interface MetaschemaTabProps { metaschemaResult: MetaschemaResult; @@ -55,55 +56,7 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa return (
- {metaschemaErrors.map((error, index) => ( -
error.instancePosition && handleGoToPosition(error.instancePosition)} - > -
-
- {error.error} -
-
-
- {error.instancePosition && ( -
- - Location: - - - Line {error.instancePosition[0]}, Col {error.instancePosition[1]} - -
- )} - {error.instanceLocation && ( -
- - Path: - - - {error.instanceLocation || '(root)'} - -
- )} - {error.keywordLocation && ( -
- - Schema: - - - {error.keywordLocation} - -
- )} -
-
- ))} +
@@ -128,12 +81,12 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa error && 'instancePosition' in error && error.instancePosition ? error.instancePosition : null; - + return ( <> -
( + items: T[], + containerWidth: number, + itemWidth: number, + gap: number +): T[][] { + const itemsPerRow = Math.max( + 1, + Math.floor((containerWidth + gap) / (itemWidth + gap)) + ); + + const rows: T[][] = []; + for (let i = 0; i < items.length; i += itemsPerRow) { + rows.push(items.slice(i, i + itemsPerRow)); + } + return rows; +} + From 354bf0f06e1a749c5640fd9681abb91fb47e0fce Mon Sep 17 00:00:00 2001 From: Ritabrata Ghosh <76sonali40@gmail.com> Date: Sat, 7 Feb 2026 16:04:31 +0530 Subject: [PATCH 2/3] stack trace ui Signed-off-by: Ritabrata Ghosh <76sonali40@gmail.com> --- webview/src/components/MetaschemaChain.tsx | 143 ------------------ .../src/components/MetaschemaStackTrace.tsx | 124 +++++++++++++++ webview/src/components/MetaschemaTab.tsx | 4 +- 3 files changed, 126 insertions(+), 145 deletions(-) delete mode 100644 webview/src/components/MetaschemaChain.tsx create mode 100644 webview/src/components/MetaschemaStackTrace.tsx diff --git a/webview/src/components/MetaschemaChain.tsx b/webview/src/components/MetaschemaChain.tsx deleted file mode 100644 index 4e69114..0000000 --- a/webview/src/components/MetaschemaChain.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import type { MetaschemaError, Position } from '../../../protocol/types'; -import { goToPosition } from '../message'; - -const BOX_WIDTH = 260; -const GAP = 12; - -interface Props { - errors: MetaschemaError[]; -} - -export function MetaschemaChain({ errors }: Props) { - const containerRef = useRef(null); - const [rows, setRows] = useState([]); - const [rowWidth, setRowWidth] = useState(0); - - useEffect(() => { - if (!containerRef.current) return; - - const compute = () => { - const width = containerRef.current!.clientWidth; - if (width < BOX_WIDTH) { - setRows(errors.map(e => [e])); - setRowWidth(BOX_WIDTH); - return; - } - - const perRow = Math.max( - 1, - Math.floor((width + GAP) / (BOX_WIDTH + GAP)) - ); - - const computedRowWidth = perRow * (BOX_WIDTH + GAP) - GAP; - - const newRows: MetaschemaError[][] = []; - for (let i = 0; i < errors.length; i += perRow) { - newRows.push(errors.slice(i, i + perRow)); - } - - setRows(newRows); - setRowWidth(computedRowWidth); - }; - compute(); - - const observer = new ResizeObserver(compute); - observer.observe(containerRef.current); - - return () => observer.disconnect(); - }, [errors]); - - return ( -
-
- {rows.map((row, rowIndex) => { - const isLTR = rowIndex % 2 === 0; - const items = isLTR ? row : [...row].reverse(); - - return ( -
- {/* ROW */} -
- {items.map((error, index) => ( -
- - - {/* Horizontal arrows */} - {index < items.length - 1 && - (isLTR ? : )} -
- ))} -
- - {/* TURN ARROW */} - {rowIndex < rows.length - 1 && ( -
-
- -
-
- )} -
- ); - })} -
-
- ); -} - -function ErrorBox({ error }: { error: MetaschemaError }) { - return ( -
- error.instancePosition && - goToPosition(error.instancePosition as Position) - } - > -
- {error.error} -
- - {error.instanceLocation && ( -
- {error.instanceLocation || '(root)'} -
- )} -
- ); -} - -function ArrowRight() { - return ; -} - -function ArrowLeft() { - return ; -} - -function ArrowDown() { - return ( -
- ↓ -
- ); -} diff --git a/webview/src/components/MetaschemaStackTrace.tsx b/webview/src/components/MetaschemaStackTrace.tsx new file mode 100644 index 0000000..acb6af5 --- /dev/null +++ b/webview/src/components/MetaschemaStackTrace.tsx @@ -0,0 +1,124 @@ +import { useState } from "react"; +import type { MetaschemaError,Position } from "../../../protocol/cli"; +import { goToPosition } from "../message"; + +interface Props { + errors: MetaschemaError[]; +} + +function ErrorBox({ + error, + size, + indent +}: { + error: MetaschemaError; + size?: 'primary' | 'stack'; + indent: number; +}) { + const clickable = Boolean(error.instancePosition); + + return ( +
+ clickable && goToPosition(error.instancePosition as Position) + } + > +
+ {size === 'stack' && ( + + )} +
+
+ {error.error} +
+ {error.instanceLocation && ( +
+ {error.instanceLocation || "(root)"} +
+ )} +
+
+
+ ); +} + + +export function MetaschemaStackTrace({errors}:Props){ + const [expanded,setExpanded]= useState(false); + + if(errors.length===0) return null; + + const [primary, ...stack] = errors; + + if (!primary) return null; + + return ( +
+ {/* Top level error */} + + + {stack.length > 0 && ( + + )} + + {/* Stack trace */} +
+
+
+ { + stack.map((err,ind)=>{ + const indent=ind*16; + return ( +
+ {ind > 0 && ( + + )} + +
+ ) + }) + } +
+
+
+
+ ) +} + + diff --git a/webview/src/components/MetaschemaTab.tsx b/webview/src/components/MetaschemaTab.tsx index 276f133..c40e75a 100644 --- a/webview/src/components/MetaschemaTab.tsx +++ b/webview/src/components/MetaschemaTab.tsx @@ -2,7 +2,7 @@ import type { MetaschemaResult, MetaschemaError, Position } from '../../../proto import { goToPosition } from '../message'; import { RawOutput } from './RawOutput'; import { CheckCircle, AlertTriangle, FileQuestion } from 'lucide-react'; -import { MetaschemaChain } from './MetaschemaChain'; +import { MetaschemaStackTrace } from './MetaschemaStackTrace'; export interface MetaschemaTabProps { metaschemaResult: MetaschemaResult; @@ -56,7 +56,7 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa return (
- +
From 66e0cb1857f160a93061e4e28fc39f2ae6a09615 Mon Sep 17 00:00:00 2001 From: Ritabrata Ghosh <76sonali40@gmail.com> Date: Sat, 14 Feb 2026 02:10:57 +0530 Subject: [PATCH 3/3] stack trace changes:01 Signed-off-by: Ritabrata Ghosh <76sonali40@gmail.com> --- webview/src/components/MetaschemaStackTrace.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/webview/src/components/MetaschemaStackTrace.tsx b/webview/src/components/MetaschemaStackTrace.tsx index acb6af5..0973001 100644 --- a/webview/src/components/MetaschemaStackTrace.tsx +++ b/webview/src/components/MetaschemaStackTrace.tsx @@ -96,16 +96,14 @@ export function MetaschemaStackTrace({errors}:Props){
{ stack.map((err,ind)=>{ - const indent=ind*16; + const STACK_INDENT = 16; return (
- {ind > 0 && ( - - )} +