Skip to content

Commit

Permalink
chore(web): Bump to React 19 (#307)
Browse files Browse the repository at this point in the history
Closes #306

Changes:
* Bump React
* Bump all Radix packages
* Replace all `forwardRef`s to using `ref` as a prop (see https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop)
munshkr authored Dec 24, 2024
2 parents 1b53ab6 + 4623d28 commit 26bd408
Showing 16 changed files with 2,428 additions and 836 deletions.
2,397 changes: 1,965 additions & 432 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions packages/web/package.json
Original file line number Diff line number Diff line change
@@ -22,14 +22,14 @@
},
"dependencies": {
"@flok-editor/server-middleware": "^1.0.1",
"@strudel/draw": "^1.1.0",
"@uiw/codemirror-theme-andromeda": "^4.22.1",
"@uiw/codemirror-theme-bespin": "^4.22.1",
"@uiw/codemirror-theme-console": "^4.22.1",
"@uiw/codemirror-theme-github": "^4.22.1",
"@uiw/codemirror-theme-monokai": "^4.22.1",
"@uiw/codemirror-theme-solarized": "^4.22.1",
"@uiw/codemirror-theme-xcode": "^4.22.1",
"@strudel/draw": "^1.1.0",
"commander": "^10.0.0",
"compression": "^1.7.4",
"express": "^4.18.2",
@@ -43,15 +43,15 @@
"@flok-editor/cm-eval": "^1.0.1",
"@flok-editor/lang-tidal": "^1.0.1",
"@flok-editor/session": "^1.1.0",
"@radix-ui/react-dialog": "^1.0.3",
"@radix-ui/react-dropdown-menu": "^2.0.4",
"@radix-ui/react-label": "^2.0.1",
"@radix-ui/react-menubar": "^1.0.2",
"@radix-ui/react-popover": "^1.0.5",
"@radix-ui/react-select": "^1.2.1",
"@radix-ui/react-toast": "^1.1.3",
"@radix-ui/react-toggle": "^1.0.2",
"@radix-ui/react-tooltip": "^1.0.5",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-dropdown-menu": "^2.1.4",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-menubar": "^1.1.4",
"@radix-ui/react-popover": "^1.1.4",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-toast": "^1.2.4",
"@radix-ui/react-toggle": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.6",
"@replit/codemirror-vim": "^6.2.1",
"@strudel/codemirror": "^1.1.0",
"@strudel/core": "^1.1.0",
@@ -86,8 +86,8 @@
"mercury-engine": "^1.2.2",
"p5": "^1.9.0",
"postcss": "^8.4.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-helmet-async": "^1.3.0",
"react-router-dom": "^6.9.0",
"tailwind-merge": "^1.10.0",
178 changes: 87 additions & 91 deletions packages/web/src/components/editor.tsx
Original file line number Diff line number Diff line change
@@ -108,101 +108,97 @@ export interface EditorProps extends ReactCodeMirrorProps {
document?: Document;
extensionSettings?: any;
settings?: EditorSettings;
ref: React.RefObject<ReactCodeMirrorRef>;
}

export const Editor = React.forwardRef(
(
{ document, settings, ...props }: EditorProps,
ref: React.ForwardedRef<ReactCodeMirrorRef>
) => {
const [mounted, setMounted] = useState(false);
const query = useQuery();
export const Editor = ({ document, settings, ref, ...props }: EditorProps) => {
const [mounted, setMounted] = useState(false);
const query = useQuery();

// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
// Make sure query parameters are set before loading the editor
if (!query) return;
setMounted(true);
}, [query]);
// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
// Make sure query parameters are set before loading the editor
if (!query) return;
setMounted(true);
}, [query]);

if (!mounted || !document) {
return null;
}
if (!mounted || !document) {
return null;
}

const { theme, fontFamily, lineNumbers, wrapText, vimMode } = {
theme: "dracula",
fontFamily: "IBM Plex Mono",
lineNumbers: false,
wrapText: false,
vimMode: false,
...settings,
};
const { theme, fontFamily, lineNumbers, wrapText, vimMode } = {
theme: "dracula",
fontFamily: "IBM Plex Mono",
lineNumbers: false,
wrapText: false,
vimMode: false,
...settings,
};

const readOnly = !!query.get("readOnly");
const language: string = langByTarget[document.target] || defaultLanguage;
const languageExtension = langExtensionsByLanguage[language] || javascript;
const extensions = [
EditorView.theme({
"&": {
fontFamily: fontFamily,
},
".cm-content": {
fontFamily: fontFamily,
},
".cm-gutters": {
fontFamily: fontFamily,
"margin-right": "10px",
},
".cm-line": {
"font-size": "105%",
"font-weight": "600",
background: "rgba(0, 0, 0, 0.7)",
"max-width": "fit-content",
padding: "0px",
},
".cm-activeLine": {
"background-color": "rgba(0, 0, 0, 1) !important",
},
"& .cm-scroller": {
minHeight: "100vh",
},
".cm-ySelectionInfo": {
opacity: "1",
fontFamily: fontFamily,
color: "black",
padding: "3px 4px",
fontSize: "0.8rem",
"font-weight": "bold",
top: "1.25em",
"z-index": "1000",
},
}),
flokSetup(document, { readOnly }),
languageExtension(),
highlightExtension,
readOnly ? EditorState.readOnly.of(true) : [],
lineNumbers ? lineNumbersExtension() : [],
vimMode ? vim() : [],
wrapText ? EditorView.lineWrapping : [],
];
const readOnly = !!query.get("readOnly");
const language: string = langByTarget[document.target] || defaultLanguage;
const languageExtension = langExtensionsByLanguage[language] || javascript;
const extensions = [
EditorView.theme({
"&": {
fontFamily: fontFamily,
},
".cm-content": {
fontFamily: fontFamily,
},
".cm-gutters": {
fontFamily: fontFamily,
"margin-right": "10px",
},
".cm-line": {
"font-size": "105%",
"font-weight": "600",
background: "rgba(0, 0, 0, 0.7)",
"max-width": "fit-content",
padding: "0px",
},
".cm-activeLine": {
"background-color": "rgba(0, 0, 0, 1) !important",
},
"& .cm-scroller": {
minHeight: "100vh",
},
".cm-ySelectionInfo": {
opacity: "1",
fontFamily: fontFamily,
color: "black",
padding: "3px 4px",
fontSize: "0.8rem",
"font-weight": "bold",
top: "1.25em",
"z-index": "1000",
},
}),
flokSetup(document, { readOnly }),
languageExtension(),
highlightExtension,
readOnly ? EditorState.readOnly.of(true) : [],
lineNumbers ? lineNumbersExtension() : [],
vimMode ? vim() : [],
wrapText ? EditorView.lineWrapping : [],
];

// If it's read-only, put a div in front of the editor so that the user
// can't interact with it.
return (
<>
{readOnly && <div className="absolute inset-0 z-10" />}
<CodeMirror
ref={ref}
value={document.content}
theme={themes[theme]?.ext || themes["dracula"]?.ext}
extensions={extensions}
basicSetup={{
foldGutter: false,
lineNumbers: false,
}}
{...props}
/>
</>
);
}
);
// If it's read-only, put a div in front of the editor so that the user
// can't interact with it.
return (
<>
{readOnly && <div className="absolute inset-0 z-10" />}
<CodeMirror
ref={ref}
value={document.content}
theme={themes[theme]?.ext || themes["dracula"]?.ext}
extensions={extensions}
basicSetup={{
foldGutter: false,
lineNumbers: false,
}}
{...props}
/>
</>
);
};
35 changes: 19 additions & 16 deletions packages/web/src/components/hydra-canvas.tsx
Original file line number Diff line number Diff line change
@@ -5,24 +5,27 @@ import { DisplaySettings } from "@/lib/display-settings";
interface HydraCanvasProps {
fullscreen?: boolean;
displaySettings: DisplaySettings;
ref: React.RefObject<HTMLCanvasElement>;
}

const HydraCanvas = React.forwardRef(
(
{ fullscreen, displaySettings }: HydraCanvasProps,
ref: React.ForwardedRef<HTMLCanvasElement>
) => (
<canvas
ref={ref}
className={cn(
"absolute top-0 left-0",
fullscreen && "h-full w-full block overflow-hidden"
)}
style={{ imageRendering: "pixelated", display: displaySettings.showCanvas ? "" : "none" }}
width={window.innerWidth / displaySettings.canvasPixelSize}
height={window.innerHeight / displaySettings.canvasPixelSize}
/>
)
const HydraCanvas = ({
fullscreen,
displaySettings,
ref,
}: HydraCanvasProps) => (
<canvas
ref={ref}
className={cn(
"absolute top-0 left-0",
fullscreen && "h-full w-full block overflow-hidden"
)}
style={{
imageRendering: "pixelated",
display: displaySettings.showCanvas ? "" : "none",
}}
width={window.innerWidth / displaySettings.canvasPixelSize}
height={window.innerHeight / displaySettings.canvasPixelSize}
/>
);

export default React.memo(HydraCanvas);
25 changes: 13 additions & 12 deletions packages/web/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -34,19 +34,20 @@ const buttonVariants = cva(

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
VariantProps<typeof buttonVariants> {
ref?: React.Ref<HTMLButtonElement>;
}

const Button = ({ className, variant, size, ref, ...props }: ButtonProps) => {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
};

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, ...props }, ref) => {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = "Button";

export { Button, buttonVariants };
79 changes: 42 additions & 37 deletions packages/web/src/components/ui/command.tsx
Original file line number Diff line number Diff line change
@@ -7,10 +7,11 @@ import { Search } from "lucide-react";
import { cn } from "../../lib/utils";
import { Dialog, DialogContent } from "./dialog";

const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => (
const Command = ({
className,
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive>) => (
<CommandPrimitive
ref={ref}
className={cn(
@@ -19,7 +20,7 @@ const Command = React.forwardRef<
)}
{...props}
/>
));
);
Command.displayName = CommandPrimitive.displayName;

interface CommandDialogProps extends DialogProps {}
@@ -36,14 +37,14 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
);
};

const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
const CommandInput = ({
className,
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive.Input>) => (
<div
className="flex items-center border-b border-b-slate-100 px-4 dark:border-b-slate-700"
cmdk-input-wrapper=""
>
cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
@@ -54,40 +55,42 @@ const CommandInput = React.forwardRef<
{...props}
/>
</div>
));
);

CommandInput.displayName = CommandPrimitive.Input.displayName;

const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
const CommandList = ({
className,
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive.List>) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
{...props}
/>
));
);

CommandList.displayName = CommandPrimitive.List.displayName;

const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => (
const CommandEmpty = ({
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive.Empty>) => (
<CommandPrimitive.Empty
ref={ref}
className="py-6 text-center text-sm"
{...props}
/>
));
);

CommandEmpty.displayName = CommandPrimitive.Empty.displayName;

const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
const CommandGroup = ({
className,
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive.Group>) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
@@ -96,26 +99,28 @@ const CommandGroup = React.forwardRef<
)}
{...props}
/>
));
);

CommandGroup.displayName = CommandPrimitive.Group.displayName;

const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
const CommandSeparator = ({
className,
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive.Separator>) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-slate-100 dark:bg-slate-700", className)}
{...props}
/>
));
);
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;

const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
const CommandItem = ({
className,
ref,
...props
}: React.ComponentProps<typeof CommandPrimitive.Item>) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
@@ -124,7 +129,7 @@ const CommandItem = React.forwardRef<
)}
{...props}
/>
));
);

CommandItem.displayName = CommandPrimitive.Item.displayName;

49 changes: 27 additions & 22 deletions packages/web/src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
@@ -19,10 +19,12 @@ const DialogPortal = ({
);
DialogPortal.displayName = DialogPrimitive.Portal.displayName;

const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, children, ...props }, ref) => (
const DialogOverlay = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) => (
<DialogPrimitive.Overlay
className={cn(
"data-[state=closed]:animate-out data-[state=open]:fade-in data-[state=closed]:fade-out fixed inset-0 z-50 bg-black/50 transition-all duration-100",
@@ -31,13 +33,15 @@ const DialogOverlay = React.forwardRef<
{...props}
ref={ref}
/>
));
);
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;

const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
const DialogContent = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof DialogPrimitive.Content>) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
@@ -47,16 +51,15 @@ const DialogContent = React.forwardRef<
"dark:bg-slate-900",
className
)}
{...props}
>
{...props}>
{children}
<DialogPrimitive.Close className="absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900 dark:data-[state=open]:bg-slate-800">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
));
);
DialogContent.displayName = DialogPrimitive.Content.displayName;

const DialogHeader = ({
@@ -87,10 +90,11 @@ const DialogFooter = ({
);
DialogFooter.displayName = "DialogFooter";

const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
const DialogTitle = ({
className,
ref,
...props
}: React.ComponentProps<typeof DialogPrimitive.Title>) => (
<DialogPrimitive.Title
ref={ref}
className={cn(
@@ -100,19 +104,20 @@ const DialogTitle = React.forwardRef<
)}
{...props}
/>
));
);
DialogTitle.displayName = DialogPrimitive.Title.displayName;

const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
const DialogDescription = ({
className,
ref,
...props
}: React.ComponentProps<typeof DialogPrimitive.Description>) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-slate-500", "dark:text-slate-400", className)}
{...props}
/>
));
);
DialogDescription.displayName = DialogPrimitive.Description.displayName;

export {
117 changes: 65 additions & 52 deletions packages/web/src/components/ui/dropdown-menu.tsx
Original file line number Diff line number Diff line change
@@ -15,32 +15,35 @@ const DropdownMenuSub = DropdownMenuPrimitive.Sub;

const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;

const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
const DropdownMenuSubTrigger = ({
className,
inset,
children,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean;
}) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm py-1.5 px-2 text-sm font-medium outline-none focus:bg-slate-100 data-[state=open]:bg-slate-100 dark:focus:bg-slate-700 dark:data-[state=open]:bg-slate-700",
inset && "pl-8",
className
)}
{...props}
>
{...props}>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
));
);
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName;

const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
const DropdownMenuSubContent = ({
className,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
@@ -49,14 +52,16 @@ const DropdownMenuSubContent = React.forwardRef<
)}
{...props}
/>
));
);
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName;

const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
const DropdownMenuContent = ({
className,
sideOffset = 4,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
@@ -68,15 +73,17 @@ const DropdownMenuContent = React.forwardRef<
{...props}
/>
</DropdownMenuPrimitive.Portal>
));
);
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;

const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
const DropdownMenuItem = ({
className,
inset,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean;
}) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
@@ -86,61 +93,66 @@ const DropdownMenuItem = React.forwardRef<
)}
{...props}
/>
));
);
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;

const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
const DropdownMenuCheckboxItem = ({
className,
children,
checked,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm font-medium outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-700",
className
)}
checked={checked}
{...props}
>
{...props}>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
));
);
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName;

const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
const DropdownMenuRadioItem = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) => (
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm font-medium outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-700",
className
)}
{...props}
>
{...props}>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
));
);
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;

const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
const DropdownMenuLabel = ({
className,
inset,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean;
}) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
@@ -150,19 +162,20 @@ const DropdownMenuLabel = React.forwardRef<
)}
{...props}
/>
));
);
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;

const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
const DropdownMenuSeparator = ({
className,
ref,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-slate-100 dark:bg-slate-700", className)}
{...props}
/>
));
);
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;

const DropdownMenuShortcut = ({
30 changes: 15 additions & 15 deletions packages/web/src/components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -3,22 +3,22 @@ import * as React from "react";
import { cn } from "@/lib/utils";

export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
extends React.InputHTMLAttributes<HTMLInputElement> {
ref?: React.Ref<HTMLInputElement>;
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, ...props }, ref) => {
return (
<input
className={cn(
"flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900",
className
)}
ref={ref}
{...props}
/>
);
}
);
const Input = ({ className, ref, ...props }: InputProps) => {
return (
<input
className={cn(
"flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900",
className
)}
ref={ref}
{...props}
/>
);
};
Input.displayName = "Input";

export { Input };
11 changes: 6 additions & 5 deletions packages/web/src/components/ui/label.tsx
Original file line number Diff line number Diff line change
@@ -5,10 +5,11 @@ import * as LabelPrimitive from "@radix-ui/react-label";

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

const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => (
const Label = ({
className,
ref,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) => (
<LabelPrimitive.Root
ref={ref}
className={cn(
@@ -17,7 +18,7 @@ const Label = React.forwardRef<
)}
{...props}
/>
));
);
Label.displayName = LabelPrimitive.Root.displayName;

export { Label };
140 changes: 78 additions & 62 deletions packages/web/src/components/ui/menubar.tsx
Original file line number Diff line number Diff line change
@@ -13,10 +13,11 @@ const MenubarSub = MenubarPrimitive.Sub;

const MenubarRadioGroup = MenubarPrimitive.RadioGroup;

const Menubar = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
>(({ className, ...props }, ref) => (
const Menubar = ({
className,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.Root>) => (
<MenubarPrimitive.Root
ref={ref}
className={cn(
@@ -25,13 +26,14 @@ const Menubar = React.forwardRef<
)}
{...props}
/>
));
);
Menubar.displayName = MenubarPrimitive.Root.displayName;

const MenubarTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
>(({ className, ...props }, ref) => (
const MenubarTrigger = ({
className,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) => (
<MenubarPrimitive.Trigger
ref={ref}
className={cn(
@@ -40,34 +42,37 @@ const MenubarTrigger = React.forwardRef<
)}
{...props}
/>
));
);
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;

const MenubarSubTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
const MenubarSubTrigger = ({
className,
inset,
children,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean;
}) => (
<MenubarPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm py-1.5 px-2 text-sm font-medium outline-none focus:bg-slate-100 data-[state=open]:bg-slate-100 dark:focus:bg-slate-700 dark:data-[state=open]:bg-slate-700",
inset && "pl-8",
className
)}
{...props}
>
{...props}>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
</MenubarPrimitive.SubTrigger>
));
);
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;

const MenubarSubContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
>(({ className, ...props }, ref) => (
const MenubarSubContent = ({
className,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) => (
<MenubarPrimitive.SubContent
ref={ref}
className={cn(
@@ -76,13 +81,15 @@ const MenubarSubContent = React.forwardRef<
)}
{...props}
/>
));
);
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;

const MenubarContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
>(({ className, align = "start", ...props }, ref) => (
const MenubarContent = ({
className,
align = "start",
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.Content>) => (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
ref={ref}
@@ -94,15 +101,17 @@ const MenubarContent = React.forwardRef<
{...props}
/>
</MenubarPrimitive.Portal>
));
);
MenubarContent.displayName = MenubarPrimitive.Content.displayName;

const MenubarItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
const MenubarItem = ({
className,
inset,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.Item> & {
inset?: boolean;
}) => (
<MenubarPrimitive.Item
ref={ref}
className={cn(
@@ -112,60 +121,65 @@ const MenubarItem = React.forwardRef<
)}
{...props}
/>
));
);
MenubarItem.displayName = MenubarPrimitive.Item.displayName;

const MenubarCheckboxItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
const MenubarCheckboxItem = ({
className,
children,
checked,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) => (
<MenubarPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm font-medium outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-700",
className
)}
checked={checked}
{...props}
>
{...props}>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.CheckboxItem>
));
);
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;

const MenubarRadioItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
const MenubarRadioItem = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) => (
<MenubarPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm font-medium outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-700",
className
)}
{...props}
>
{...props}>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.RadioItem>
));
);
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;

const MenubarLabel = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
const MenubarLabel = ({
className,
inset,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.Label> & {
inset?: boolean;
}) => (
<MenubarPrimitive.Label
ref={ref}
className={cn(
@@ -175,19 +189,21 @@ const MenubarLabel = React.forwardRef<
)}
{...props}
/>
));
);

MenubarLabel.displayName = MenubarPrimitive.Label.displayName;

const MenubarSeparator = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
>(({ className, ...props }, ref) => (
const MenubarSeparator = ({
className,
ref,
...props
}: React.ComponentProps<typeof MenubarPrimitive.Separator>) => (
<MenubarPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-slate-100 dark:bg-slate-700", className)}
{...props}
/>
));
);
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;

const MenubarShortcut = ({
13 changes: 8 additions & 5 deletions packages/web/src/components/ui/popover.tsx
Original file line number Diff line number Diff line change
@@ -9,10 +9,13 @@ const Popover = PopoverPrimitive.Root;

const PopoverTrigger = PopoverPrimitive.Trigger;

const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
const PopoverContent = ({
className,
align = "center",
sideOffset = 4,
ref,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Content>) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
@@ -25,7 +28,7 @@ const PopoverContent = React.forwardRef<
{...props}
/>
</PopoverPrimitive.Portal>
));
);
PopoverContent.displayName = PopoverPrimitive.Content.displayName;

export { Popover, PopoverTrigger, PopoverContent };
67 changes: 36 additions & 31 deletions packages/web/src/components/ui/select.tsx
Original file line number Diff line number Diff line change
@@ -12,49 +12,52 @@ const SelectGroup = SelectPrimitive.Group;

const SelectValue = SelectPrimitive.Value;

const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
const SelectTrigger = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof SelectPrimitive.Trigger>) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900",
className
)}
{...props}
>
{...props}>
{children}
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Trigger>
));
);
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;

const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, ...props }, ref) => (
const SelectContent = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof SelectPrimitive.Content>) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"animate-in fade-in-80 relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
className
)}
{...props}
>
{...props}>
<SelectPrimitive.Viewport className="p-1">
{children}
</SelectPrimitive.Viewport>
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
));
);
SelectContent.displayName = SelectPrimitive.Content.displayName;

const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
const SelectLabel = ({
className,
ref,
...props
}: React.ComponentProps<typeof SelectPrimitive.Label>) => (
<SelectPrimitive.Label
ref={ref}
className={cn(
@@ -63,21 +66,22 @@ const SelectLabel = React.forwardRef<
)}
{...props}
/>
));
);
SelectLabel.displayName = SelectPrimitive.Label.displayName;

const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
const SelectItem = ({
className,
children,
ref,
...props
}: React.ComponentProps<typeof SelectPrimitive.Item>) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm font-medium outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-700",
className
)}
{...props}
>
{...props}>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
@@ -86,19 +90,20 @@ const SelectItem = React.forwardRef<

<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
));
);
SelectItem.displayName = SelectPrimitive.Item.displayName;

const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
const SelectSeparator = ({
className,
ref,
...props
}: React.ComponentProps<typeof SelectPrimitive.Separator>) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-slate-100 dark:bg-slate-700", className)}
{...props}
/>
));
);
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;

export {
72 changes: 39 additions & 33 deletions packages/web/src/components/ui/toast.tsx
Original file line number Diff line number Diff line change
@@ -6,10 +6,11 @@ import { cn } from "../../lib/utils";

const ToastProvider = ToastPrimitives.Provider;

const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
const ToastViewport = ({
className,
ref,
...props
}: React.ComponentProps<typeof ToastPrimitives.Viewport>) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
@@ -18,7 +19,7 @@ const ToastViewport = React.forwardRef<
)}
{...props}
/>
));
);
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;

const toastVariants = cva(
@@ -40,25 +41,28 @@ const toastVariants = cva(
}
);

const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
const Toast = ({
className,
variant,
ref,
...props
}: React.ComponentProps<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants>) => {
return (
<ToastPrimitives.Root
ref={ref}
className={cn(toastVariants({ variant }), className)}
{...props}
/>
);
});
};
Toast.displayName = ToastPrimitives.Root.displayName;

const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
const ToastAction = ({
className,
ref,
...props
}: React.ComponentProps<typeof ToastPrimitives.Action>) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
@@ -67,49 +71,51 @@ const ToastAction = React.forwardRef<
)}
{...props}
/>
));
);
ToastAction.displayName = ToastPrimitives.Action.displayName;

const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
const ToastClose = ({
className,
ref,
...props
}: React.ComponentProps<typeof ToastPrimitives.Close>) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute top-2 right-2 rounded-md p-1 text-slate-500 opacity-0 transition-opacity hover:text-slate-900 focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600 dark:hover:text-slate-50",
className
)}
toast-close=""
{...props}
>
{...props}>
<X className="h-4 w-4" />
</ToastPrimitives.Close>
));
);
ToastClose.displayName = ToastPrimitives.Close.displayName;

const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
const ToastTitle = ({
className,
ref,
...props
}: React.ComponentProps<typeof ToastPrimitives.Title>) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-sm font-semibold", className)}
{...props}
/>
));
);
ToastTitle.displayName = ToastPrimitives.Title.displayName;

const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
const ToastDescription = ({
className,
ref,
...props
}: React.ComponentProps<typeof ToastPrimitives.Description>) => (
<ToastPrimitives.Description
ref={ref}
className={cn("text-sm opacity-90 overflow-auto", className)}
{...props}
/>
));
);
ToastDescription.displayName = ToastPrimitives.Description.displayName;

type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
15 changes: 9 additions & 6 deletions packages/web/src/components/ui/toggle.tsx
Original file line number Diff line number Diff line change
@@ -28,17 +28,20 @@ const toggleVariants = cva(
}
);

const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants>
>(({ className, variant, size, ...props }, ref) => (
const Toggle = ({
className,
variant,
size,
ref,
...props
}: React.ComponentProps<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants>) => (
<TogglePrimitive.Root
ref={ref}
className={cn(toggleVariants({ variant, size, className }))}
{...props}
/>
));
);

Toggle.displayName = TogglePrimitive.Root.displayName;

12 changes: 7 additions & 5 deletions packages/web/src/components/ui/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -12,10 +12,12 @@ Tooltip.displayName = TooltipPrimitive.Tooltip.displayName;

const TooltipTrigger = TooltipPrimitive.Trigger;

const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
const TooltipContent = ({
className,
sideOffset = 4,
ref,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) => (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
@@ -25,7 +27,7 @@ const TooltipContent = React.forwardRef<
)}
{...props}
/>
));
);
TooltipContent.displayName = TooltipPrimitive.Content.displayName;

export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };

0 comments on commit 26bd408

Please sign in to comment.