Skyvern Evaluation New Endpoint - general /runs (#2374)
This commit is contained in:
@@ -9,6 +9,8 @@ const buttonVariants = cva(
|
||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90 font-bold",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
disabled:
|
||||
"hover:bg-accent hover:text-accent-foreground opacity-50 pointer-events-none",
|
||||
outline:
|
||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
|
||||
60
skyvern-frontend/src/components/ui/grid-form.tsx
Normal file
60
skyvern-frontend/src/components/ui/grid-form.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React, { useMemo, useId } from "react";
|
||||
|
||||
type Breakpoints = Record<number, number>; // { columns: minWidth }
|
||||
|
||||
type GridFormProps = {
|
||||
breakpoints: Breakpoints;
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* GridForm is a layout component that wraps its children in a CSS grid.
|
||||
* Pass the breakpoints prop as an object mapping columns to min viewport width.
|
||||
*
|
||||
* Example usage:
|
||||
* <GridForm breakpoints={{ 1: 600, 2: 900 }}>
|
||||
* <Item1 />
|
||||
* <Item2 />
|
||||
* </GridForm>
|
||||
*/
|
||||
export const GridForm: React.FC<GridFormProps> = ({
|
||||
breakpoints,
|
||||
className = "",
|
||||
children,
|
||||
}) => {
|
||||
// Generate a unique className for this instance
|
||||
const uniqueClass = `grid-form-${useId().replace(/:/g, "-")}`;
|
||||
|
||||
// Generate CSS for breakpoints
|
||||
const styleTag = useMemo(() => {
|
||||
// Sort breakpoints by minWidth ascending
|
||||
const sorted = Object.entries(breakpoints)
|
||||
.map(
|
||||
([cols, minWidth]) =>
|
||||
[parseInt(cols, 10), minWidth] as [number, number],
|
||||
)
|
||||
.sort((a, b) => a[1] - b[1]);
|
||||
let css = `.${uniqueClass} { display: grid; gap: 1rem; }\n`;
|
||||
for (const [cols, minWidth] of sorted) {
|
||||
css += `@media (min-width: ${minWidth}px) { .${uniqueClass} { grid-template-columns: repeat(${cols}, minmax(0, 1fr)); } }\n`;
|
||||
}
|
||||
// Default to the smallest breakpoint (first one)
|
||||
if (sorted.length > 0 && sorted[0]) {
|
||||
const [firstCols, firstMinWidth] = sorted[0];
|
||||
css += `@media (max-width: ${firstMinWidth}px) { .${uniqueClass} { grid-template-columns: repeat(${firstCols}, minmax(0, 1fr)); } }\n`;
|
||||
}
|
||||
return <style>{css}</style>;
|
||||
}, [breakpoints, uniqueClass]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{styleTag}
|
||||
<div className={`${uniqueClass} ${className}`}>{children}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
GridForm.displayName = "GridForm";
|
||||
|
||||
export default GridForm;
|
||||
@@ -41,12 +41,14 @@ PaginationItem.displayName = "PaginationItem";
|
||||
|
||||
type PaginationLinkProps = {
|
||||
isActive?: boolean;
|
||||
isDisabled?: boolean;
|
||||
} & Pick<ButtonProps, "size"> &
|
||||
React.ComponentProps<"a">;
|
||||
|
||||
const PaginationLink = ({
|
||||
className,
|
||||
isActive,
|
||||
isDisabled,
|
||||
size = "icon",
|
||||
...props
|
||||
}: PaginationLinkProps) => (
|
||||
@@ -54,10 +56,11 @@ const PaginationLink = ({
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
variant: isActive ? "outline" : "ghost",
|
||||
variant: isDisabled ? "disabled" : isActive ? "outline" : "ghost",
|
||||
size,
|
||||
}),
|
||||
className,
|
||||
"cursor-pointer select-none",
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
52
skyvern-frontend/src/components/ui/search.tsx
Normal file
52
skyvern-frontend/src/components/ui/search.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import * as React from "react";
|
||||
import { Input } from "./input";
|
||||
import { SearchIcon } from "../icons/SearchIcon";
|
||||
import { cn } from "@/util/utils";
|
||||
|
||||
interface SearchProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
value: string;
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export const Search = React.forwardRef<HTMLInputElement, SearchProps>(
|
||||
(
|
||||
{
|
||||
value,
|
||||
onChange,
|
||||
placeholder = "Search...",
|
||||
className,
|
||||
label = "Search",
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
return (
|
||||
<div className={cn("min-w-6rem relative flex items-center", className)}>
|
||||
<label htmlFor={props.id} className="sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<span className="pointer-events-none absolute left-3 text-muted-foreground">
|
||||
<SearchIcon className="h-4 w-4" />
|
||||
</span>
|
||||
<Input
|
||||
ref={ref}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
placeholder={placeholder}
|
||||
className={cn(
|
||||
"h-full rounded-sm py-3.5 pl-10",
|
||||
props.disabled && "opacity-50",
|
||||
)}
|
||||
aria-label={label}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
Search.displayName = "Search";
|
||||
|
||||
export default Search;
|
||||
Reference in New Issue
Block a user