Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,17 @@ Then, put this in your React app:

```tsx
import { useState } from "react";
import { getElementContext, freeze, unfreeze, openFile, type ReactGrabElementContext } from "react-grab/primitives";

const useElementSelector = (onSelect: (context: ReactGrabElementContext) => void) => {
import {
getElementContext,
freeze,
unfreeze,
openFile,
type ReactGrabElementContext,
} from "react-grab/primitives";

const useElementSelector = (
onSelect: (context: ReactGrabElementContext) => void,
) => {
const [isActive, setIsActive] = useState(false);

const startSelecting = () => {
Expand Down
21 changes: 18 additions & 3 deletions packages/cli/src/utils/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -787,13 +787,28 @@ export const previewTransform = (
);

case "vite":
return transformVite(projectRoot, agent, reactGrabAlreadyConfigured, force);
return transformVite(
projectRoot,
agent,
reactGrabAlreadyConfigured,
force,
);

case "tanstack":
return transformTanStack(projectRoot, agent, reactGrabAlreadyConfigured, force);
return transformTanStack(
projectRoot,
agent,
reactGrabAlreadyConfigured,
force,
);

case "webpack":
return transformWebpack(projectRoot, agent, reactGrabAlreadyConfigured, force);
return transformWebpack(
projectRoot,
agent,
reactGrabAlreadyConfigured,
force,
);

default:
return {
Expand Down
9 changes: 8 additions & 1 deletion packages/demo/components/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,14 @@ export function Dashboard() {
</SelectContent>
</Select>
{/* BUG: Export button uses ghost variant — nearly invisible in dark mode */}
<Button size="sm" variant="ghost" className="" onClick={() => { throw new Error("exportDashboard is not a function"); }}>
<Button
size="sm"
variant="ghost"
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Change the variant to fix the visibility bug noted in the comment directly above (e.g., use 'outline' or 'secondary' instead of 'ghost').

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/demo/components/dashboard.tsx, line 123:

<comment>Change the variant to fix the visibility bug noted in the comment directly above (e.g., use 'outline' or 'secondary' instead of 'ghost').</comment>

<file context>
@@ -118,7 +118,14 @@ export function Dashboard() {
-          <Button size="sm" variant="ghost" className="" onClick={() => { throw new Error("exportDashboard is not a function"); }}>
+          <Button
+            size="sm"
+            variant="ghost"
+            className=""
+            onClick={() => {
</file context>
Suggested change
variant="ghost"
variant="outline"
Fix with Cubic

className=""
onClick={() => {
throw new Error("exportDashboard is not a function");
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Use console.warn instead of throwing a raw error for unimplemented features to prevent triggering error trackers and polluting the console with uncaught exceptions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/demo/components/dashboard.tsx, line 126:

<comment>Use `console.warn` instead of throwing a raw error for unimplemented features to prevent triggering error trackers and polluting the console with uncaught exceptions.</comment>

<file context>
@@ -118,7 +118,14 @@ export function Dashboard() {
+            variant="ghost"
+            className=""
+            onClick={() => {
+              throw new Error("exportDashboard is not a function");
+            }}
+          >
</file context>
Suggested change
throw new Error("exportDashboard is not a function");
console.warn("exportDashboard is not a function");
Fix with Cubic

}}
>
Export
</Button>
</div>
Expand Down
18 changes: 9 additions & 9 deletions packages/demo/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const badgeVariants = cva(
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
Expand All @@ -22,8 +22,8 @@ const badgeVariants = cva(
defaultVariants: {
variant: "default",
},
}
)
},
);

function Badge({
className,
Expand All @@ -32,15 +32,15 @@ function Badge({
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span"
const Comp = asChild ? Slot : "span";

return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
)
);
}

export { Badge, badgeVariants }
export { Badge, badgeVariants };
20 changes: 10 additions & 10 deletions packages/demo/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
Expand Down Expand Up @@ -33,8 +33,8 @@ const buttonVariants = cva(
variant: "default",
size: "default",
},
}
)
},
);

function Button({
className,
Expand All @@ -44,17 +44,17 @@ function Button({
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
asChild?: boolean;
}) {
const Comp = asChild ? Slot : "button"
const Comp = asChild ? Slot : "button";

return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
);
}

export { Button, buttonVariants }
export { Button, buttonVariants };
26 changes: 13 additions & 13 deletions packages/demo/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import * as React from "react"
import * as React from "react";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

function Card({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card"
className={cn(
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
className
className,
)}
{...props}
/>
)
);
}

function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
Expand All @@ -21,11 +21,11 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-header"
className={cn(
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
className
className,
)}
{...props}
/>
)
);
}

function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
Expand All @@ -35,7 +35,7 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
className={cn("leading-none font-semibold", className)}
{...props}
/>
)
);
}

function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
Expand All @@ -45,7 +45,7 @@ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
);
}

function CardAction({ className, ...props }: React.ComponentProps<"div">) {
Expand All @@ -54,11 +54,11 @@ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
className,
)}
{...props}
/>
)
);
}

function CardContent({ className, ...props }: React.ComponentProps<"div">) {
Expand All @@ -68,7 +68,7 @@ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
className={cn("px-6", className)}
{...props}
/>
)
);
}

function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
Expand All @@ -78,7 +78,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
{...props}
/>
)
);
}

export {
Expand All @@ -89,4 +89,4 @@ export {
CardAction,
CardDescription,
CardContent,
}
};
10 changes: 5 additions & 5 deletions packages/demo/components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react"
import * as React from "react";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
Expand All @@ -11,11 +11,11 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
className,
)}
{...props}
/>
)
);
}

export { Input }
export { Input };
Loading
Loading