Back to React

This commit is contained in:
Gregory Schier
2023-03-13 09:50:49 -07:00
parent fa1f33a2ac
commit c6653af782
25 changed files with 377 additions and 616 deletions

View File

@@ -1,13 +1,31 @@
import { Router } from 'preact-router';
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Workspaces } from '../pages/Workspaces';
import { Workspace } from '../pages/Workspace';
import { RouteError } from "./RouteError";
const router = createBrowserRouter([
{
path: '/',
errorElement: <RouteError />,
children: [
{
path: '/',
element: <Workspaces />,
},
{
path: '/workspaces/:workspaceId',
element: <Workspace />,
},
{
path: '/workspaces/:workspaceId/requests/:requestId',
element: <Workspace />,
},
],
},
]);
export function AppRouter() {
return (
<Router>
<Workspaces path="/" />
<Workspace path="/workspaces/:workspaceId" />
<Workspace path="/workspaces/:workspaceId/requests/:requestId" />
</Router>
<RouterProvider router={router} />
);
}

View File

@@ -1,7 +1,7 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import { Link } from 'preact-router';
import { forwardRef } from 'preact/compat';
import type { KeyboardEvent, MouseEvent, ReactNode } from 'react';
import { forwardRef } from 'react';
import { Link } from 'react-router-dom';
import { Icon } from './Icon';
const colorStyles = {
@@ -15,18 +15,18 @@ const colorStyles = {
};
export type ButtonProps = {
href?: string;
to?: string;
color?: keyof typeof colorStyles;
size?: 'sm' | 'md';
justify?: 'start' | 'center';
type?: 'button' | 'submit';
onClick?: (event: MouseEvent) => void;
onDoubleClick?: (event: MouseEvent) => void;
onClick?: (event: MouseEvent<HTMLElement>) => void;
onDoubleClick?: (event: MouseEvent<HTMLElement>) => void;
contentEditable?: boolean;
onKeyDown?: (event: KeyboardEvent) => void;
onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void;
forDropdown?: boolean;
className?: string;
children?: ComponentChildren;
children?: ReactNode;
disabled?: boolean;
title?: string;
tabIndex?: number;
@@ -34,30 +34,60 @@ export type ButtonProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const Button = forwardRef<any, ButtonProps>(function Button(
{ href, className, children, forDropdown, color, justify = 'center', size = 'md', ...props },
{
to,
className,
children,
forDropdown,
color,
justify = 'center',
size = 'md',
...props
}: ButtonProps,
ref,
) {
// const Component = 'button';
const Component = typeof href === 'string' ? Link : 'button';
return (
<Component
ref={ref}
href={href}
className={classnames(
className,
'outline-none',
'border border-transparent focus-visible:border-blue-300',
'rounded-md flex items-center',
colorStyles[color || 'default'],
justify === 'start' && 'justify-start',
justify === 'center' && 'justify-center',
size === 'md' && 'h-9 px-3',
size === 'sm' && 'h-7 px-2.5 text-sm',
)}
{...props}
>
{children}
{forDropdown && <Icon icon="triangleDown" className="ml-1 -mr-1" />}
</Component>
);
if (typeof to === 'string') {
return (
<Link
ref={ref}
to={to}
className={classnames(
className,
'outline-none',
'border border-transparent focus-visible:border-blue-300',
'rounded-md flex items-center',
colorStyles[color || 'default'],
justify === 'start' && 'justify-start',
justify === 'center' && 'justify-center',
size === 'md' && 'h-9 px-3',
size === 'sm' && 'h-7 px-2.5 text-sm',
)}
{...props}
>
{children}
{forDropdown && <Icon icon="triangleDown" className="ml-1 -mr-1" />}
</Link>
);
} else {
return (
<button
ref={ref}
className={classnames(
className,
'outline-none',
'border border-transparent focus-visible:border-blue-300',
'rounded-md flex items-center',
colorStyles[color || 'default'],
justify === 'start' && 'justify-start',
justify === 'center' && 'justify-center',
size === 'md' && 'h-9 px-3',
size === 'sm' && 'h-7 px-2.5 text-sm',
)}
{...props}
>
{children}
{forDropdown && <Icon icon="triangleDown" className="ml-1 -mr-1" />}
</button>
);
}
});

View File

@@ -3,16 +3,11 @@ import type { ButtonProps } from './Button';
import { Button } from './Button';
type Props = ButtonProps & {
href: string;
to: string;
};
export function ButtonLink({ href, className, ...buttonProps }: Props) {
export function ButtonLink({ to, className, ...buttonProps }: Props) {
return (
<Button
href={href}
className={classnames(className, 'w-full')}
tabIndex={-1}
{...buttonProps}
/>
<Button to={to} className={classnames(className, 'w-full')} tabIndex={-1} {...buttonProps} />
);
}

View File

@@ -1,12 +1,12 @@
import * as D from '@radix-ui/react-dialog';
import classnames from 'classnames';
import { motion } from 'framer-motion';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
import { IconButton } from './IconButton';
import { HStack, VStack } from './Stacks';
interface Props {
children: ComponentChildren;
children: ReactNode;
open: boolean;
onOpenChange: (open: boolean) => void;
title: string;

View File

@@ -2,12 +2,11 @@ import * as D from '@radix-ui/react-dropdown-menu';
import { CheckIcon } from '@radix-ui/react-icons';
import classnames from 'classnames';
import { motion } from 'framer-motion';
import type { ComponentChildren } from 'preact';
import type { ForwardedRef } from 'preact/compat';
import type { ReactNode, ForwardedRef } from 'react';
import { forwardRef, useImperativeHandle, useLayoutEffect, useState } from 'react';
interface DropdownMenuRadioProps {
children: ComponentChildren;
children: ReactNode;
onValueChange: ((v: { label: string; value: string }) => void) | null;
value: string;
label?: string;
@@ -51,13 +50,13 @@ export function DropdownMenuRadio({
}
export interface DropdownProps {
children: ComponentChildren;
children: ReactNode;
items: (
| {
label: string;
onSelect?: () => void;
disabled?: boolean;
leftSlot?: ComponentChildren;
leftSlot?: ReactNode;
}
| '-----'
)[];
@@ -92,7 +91,7 @@ export function Dropdown({ children, items }: DropdownProps) {
}
interface DropdownMenuPortalProps {
children: ComponentChildren;
children: ReactNode;
}
function DropdownMenuPortal({ children }: DropdownMenuPortalProps) {
@@ -265,7 +264,7 @@ function DropdownMenuSeparator({ className, ...props }: D.DropdownMenuSeparatorP
}
type DropdownMenuTriggerProps = D.DropdownMenuTriggerProps & {
children: ComponentChildren;
children: ReactNode;
className?: string;
};
@@ -278,9 +277,9 @@ function DropdownMenuTrigger({ children, className, ...props }: DropdownMenuTrig
}
interface ItemInnerProps {
leftSlot?: ComponentChildren;
rightSlot?: ComponentChildren;
children: ComponentChildren;
leftSlot?: ReactNode;
rightSlot?: ReactNode;
children: ReactNode;
noHover?: boolean;
className?: string;
}

View File

@@ -1,5 +1,5 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
const colsClasses: Record<string | number, string> = {
none: 'grid-cols-none',
@@ -29,7 +29,7 @@ interface Props {
cols?: keyof typeof colsClasses;
gap?: keyof typeof gapClasses;
className?: string;
children?: ComponentChildren;
children?: ReactNode;
}
export function Grid({ className, cols, gap, children }: Props) {

View File

@@ -1,9 +1,9 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
type Props = {
className?: string;
children?: ComponentChildren;
children?: ReactNode;
};
export function Heading({ className, children, ...props }: Props) {

View File

@@ -1,5 +1,5 @@
import classnames from 'classnames';
import { forwardRef } from 'preact/compat';
import { forwardRef } from "react";
import type { ButtonProps } from './Button';
import { Button } from './Button';
import type { IconProps } from './Icon';

View File

@@ -1,5 +1,5 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
import type { EditorProps } from './Editor';
import { Editor } from './Editor';
import { HStack, VStack } from './Stacks';
@@ -13,8 +13,8 @@ interface Props {
onChange?: (value: string) => void;
useEditor?: Pick<EditorProps, 'contentType' | 'useTemplating'>;
defaultValue?: string;
leftSlot?: ComponentChildren;
rightSlot?: ComponentChildren;
leftSlot?: ReactNode;
rightSlot?: ReactNode;
size?: 'sm' | 'md';
className?: string;
placeholder?: string;

View File

@@ -0,0 +1,23 @@
import { useRouteError } from 'react-router-dom';
import { ButtonLink } from './ButtonLink';
import { Heading } from './Heading';
import { VStack } from './Stacks';
export function RouteError() {
const error = useRouteError();
const stringified = JSON.stringify(error);
const message = (error as any).message ?? stringified;
return (
<div className="flex items-center justify-center h-full">
<VStack space={5} className="max-w-[30rem] !h-auto">
<Heading>Route Error 🔥</Heading>
<pre className="text-sm select-auto cursor-text bg-gray-100 p-3 rounded whitespace-normal">
{message}
</pre>
<ButtonLink to="/" color="primary">
Go Home
</ButtonLink>
</VStack>
</div>
);
}

View File

@@ -1,9 +1,9 @@
import * as S from '@radix-ui/react-scroll-area';
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
interface Props {
children: ComponentChildren;
children: ReactNode;
className?: string;
}

View File

@@ -75,7 +75,7 @@ function SidebarItem({ request, active }: { request: HttpRequest; active: boolea
? 'bg-gray-200/70 text-gray-900'
: 'text-gray-600 hover:text-gray-800 active:bg-gray-200/30',
)}
href={`/workspaces/${request.workspaceId}/requests/${request.id}`}
to={`/workspaces/${request.workspaceId}/requests/${request.id}`}
contentEditable={editing}
onDoubleClick={() => setEditing(true)}
justify="start"

View File

@@ -1,5 +1,5 @@
import classnames from 'classnames';
import type { ComponentChildren, ComponentType } from 'preact';
import type { ComponentType, ReactNode } from 'react';
import { Children, Fragment } from 'react';
const spaceClassesX = {
@@ -24,7 +24,7 @@ const spaceClassesY = {
interface HStackProps extends BaseStackProps {
space?: keyof typeof spaceClassesX;
children?: ComponentChildren;
children?: ReactNode;
}
export function HStack({ className, space, children, ...props }: HStackProps) {
@@ -52,7 +52,7 @@ export function HStack({ className, space, children, ...props }: HStackProps) {
export interface VStackProps extends BaseStackProps {
space?: keyof typeof spaceClassesY;
children: ComponentChildren;
children: ReactNode;
}
export function VStack({ className, space, children, ...props }: VStackProps) {
@@ -83,7 +83,7 @@ interface BaseStackProps {
alignItems?: 'start' | 'center';
justifyContent?: 'start' | 'center' | 'end';
className?: string;
children?: ComponentChildren;
children?: ReactNode;
}
function BaseStack({ className, alignItems, justifyContent, children, as }: BaseStackProps) {

View File

@@ -1,9 +1,9 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
interface Props {
statusCode: number;
children: ComponentChildren;
children: ReactNode;
}
export function StatusColor({ statusCode, children }: Props) {

View File

@@ -1,6 +1,6 @@
import * as T from '@radix-ui/react-tabs';
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
import { useState } from 'react';
import { Button } from './Button';
import { ScrollArea } from './ScrollArea';
@@ -11,10 +11,10 @@ import './Tabs.css';
interface Props {
defaultValue?: string;
label: string;
tabs: { value: string; label: ComponentChildren }[];
tabs: { value: string; label: ReactNode }[];
tabListClassName?: string;
className?: string;
children: ComponentChildren;
children: ReactNode;
}
export function Tabs({ defaultValue, label, children, tabs, className, tabListClassName }: Props) {
@@ -50,7 +50,7 @@ export function Tabs({ defaultValue, label, children, tabs, className, tabListCl
interface TabTriggerProps {
value: string;
children: ComponentChildren;
children: ReactNode;
active?: boolean;
}
@@ -72,7 +72,7 @@ export function TabTrigger({ value, children, active }: TabTriggerProps) {
interface TabContentProps {
value: string;
children: ComponentChildren;
children: ReactNode;
className?: string;
}

View File

@@ -1,9 +1,9 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';
import type { ReactNode } from 'react';
interface Props {
className?: string;
children?: ComponentChildren;
children?: ReactNode;
}
export function WindowDragRegion({ className, ...props }: Props) {