mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 00:58:32 +02:00
Back to React
This commit is contained in:
721
package-lock.json
generated
721
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -34,23 +34,26 @@
|
|||||||
"@radix-ui/react-tabs": "^1.0.3",
|
"@radix-ui/react-tabs": "^1.0.3",
|
||||||
"@tanstack/react-query": "^4.24.10",
|
"@tanstack/react-query": "^4.24.10",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
|
"@vitejs/plugin-react": "^3.1.0",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.8.1",
|
||||||
"cm6-graphql": "^0.0.4-canary-b30a2325.0",
|
"cm6-graphql": "^0.0.4-canary-b30a2325.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"format-graphql": "^1.4.0",
|
"format-graphql": "^1.4.0",
|
||||||
"framer-motion": "^9.0.4",
|
"framer-motion": "^9.0.4",
|
||||||
"parse-color": "^1.0.0",
|
"parse-color": "^1.0.0",
|
||||||
"preact-router": "^4.1.0",
|
|
||||||
"react-helmet-async": "^1.3.0",
|
"react-helmet-async": "^1.3.0",
|
||||||
"react-use": "^17.4.0"
|
"react-use": "^17.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@preact/preset-vite": "^2.5.0",
|
|
||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@types/parse-color": "^1.0.1",
|
"@types/parse-color": "^1.0.1",
|
||||||
"@types/parse-json": "^4.0.0",
|
"@types/parse-json": "^4.0.0",
|
||||||
|
"@types/react-dom": "^18.0.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
||||||
"@typescript-eslint/parser": "^5.52.0",
|
"@typescript-eslint/parser": "^5.52.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
|
|||||||
Binary file not shown.
@@ -1,13 +1,31 @@
|
|||||||
import { Router } from 'preact-router';
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import { Workspaces } from '../pages/Workspaces';
|
import { Workspaces } from '../pages/Workspaces';
|
||||||
import { Workspace } from '../pages/Workspace';
|
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() {
|
export function AppRouter() {
|
||||||
return (
|
return (
|
||||||
<Router>
|
<RouterProvider router={router} />
|
||||||
<Workspaces path="/" />
|
|
||||||
<Workspace path="/workspaces/:workspaceId" />
|
|
||||||
<Workspace path="/workspaces/:workspaceId/requests/:requestId" />
|
|
||||||
</Router>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { KeyboardEvent, MouseEvent, ReactNode } from 'react';
|
||||||
import { Link } from 'preact-router';
|
import { forwardRef } from 'react';
|
||||||
import { forwardRef } from 'preact/compat';
|
import { Link } from 'react-router-dom';
|
||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
|
|
||||||
const colorStyles = {
|
const colorStyles = {
|
||||||
@@ -15,18 +15,18 @@ const colorStyles = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ButtonProps = {
|
export type ButtonProps = {
|
||||||
href?: string;
|
to?: string;
|
||||||
color?: keyof typeof colorStyles;
|
color?: keyof typeof colorStyles;
|
||||||
size?: 'sm' | 'md';
|
size?: 'sm' | 'md';
|
||||||
justify?: 'start' | 'center';
|
justify?: 'start' | 'center';
|
||||||
type?: 'button' | 'submit';
|
type?: 'button' | 'submit';
|
||||||
onClick?: (event: MouseEvent) => void;
|
onClick?: (event: MouseEvent<HTMLElement>) => void;
|
||||||
onDoubleClick?: (event: MouseEvent) => void;
|
onDoubleClick?: (event: MouseEvent<HTMLElement>) => void;
|
||||||
contentEditable?: boolean;
|
contentEditable?: boolean;
|
||||||
onKeyDown?: (event: KeyboardEvent) => void;
|
onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void;
|
||||||
forDropdown?: boolean;
|
forDropdown?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: ComponentChildren;
|
children?: ReactNode;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
tabIndex?: number;
|
tabIndex?: number;
|
||||||
@@ -34,30 +34,60 @@ export type ButtonProps = {
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const Button = forwardRef<any, ButtonProps>(function Button(
|
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,
|
ref,
|
||||||
) {
|
) {
|
||||||
// const Component = 'button';
|
if (typeof to === 'string') {
|
||||||
const Component = typeof href === 'string' ? Link : 'button';
|
return (
|
||||||
return (
|
<Link
|
||||||
<Component
|
ref={ref}
|
||||||
ref={ref}
|
to={to}
|
||||||
href={href}
|
className={classnames(
|
||||||
className={classnames(
|
className,
|
||||||
className,
|
'outline-none',
|
||||||
'outline-none',
|
'border border-transparent focus-visible:border-blue-300',
|
||||||
'border border-transparent focus-visible:border-blue-300',
|
'rounded-md flex items-center',
|
||||||
'rounded-md flex items-center',
|
colorStyles[color || 'default'],
|
||||||
colorStyles[color || 'default'],
|
justify === 'start' && 'justify-start',
|
||||||
justify === 'start' && 'justify-start',
|
justify === 'center' && 'justify-center',
|
||||||
justify === 'center' && 'justify-center',
|
size === 'md' && 'h-9 px-3',
|
||||||
size === 'md' && 'h-9 px-3',
|
size === 'sm' && 'h-7 px-2.5 text-sm',
|
||||||
size === 'sm' && 'h-7 px-2.5 text-sm',
|
)}
|
||||||
)}
|
{...props}
|
||||||
{...props}
|
>
|
||||||
>
|
{children}
|
||||||
{children}
|
{forDropdown && <Icon icon="triangleDown" className="ml-1 -mr-1" />}
|
||||||
{forDropdown && <Icon icon="triangleDown" className="ml-1 -mr-1" />}
|
</Link>
|
||||||
</Component>
|
);
|
||||||
);
|
} 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,16 +3,11 @@ import type { ButtonProps } from './Button';
|
|||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
|
|
||||||
type Props = ButtonProps & {
|
type Props = ButtonProps & {
|
||||||
href: string;
|
to: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ButtonLink({ href, className, ...buttonProps }: Props) {
|
export function ButtonLink({ to, className, ...buttonProps }: Props) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button to={to} className={classnames(className, 'w-full')} tabIndex={-1} {...buttonProps} />
|
||||||
href={href}
|
|
||||||
className={classnames(className, 'w-full')}
|
|
||||||
tabIndex={-1}
|
|
||||||
{...buttonProps}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import * as D from '@radix-ui/react-dialog';
|
import * as D from '@radix-ui/react-dialog';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
import { IconButton } from './IconButton';
|
import { IconButton } from './IconButton';
|
||||||
import { HStack, VStack } from './Stacks';
|
import { HStack, VStack } from './Stacks';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ import * as D from '@radix-ui/react-dropdown-menu';
|
|||||||
import { CheckIcon } from '@radix-ui/react-icons';
|
import { CheckIcon } from '@radix-ui/react-icons';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode, ForwardedRef } from 'react';
|
||||||
import type { ForwardedRef } from 'preact/compat';
|
|
||||||
import { forwardRef, useImperativeHandle, useLayoutEffect, useState } from 'react';
|
import { forwardRef, useImperativeHandle, useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
interface DropdownMenuRadioProps {
|
interface DropdownMenuRadioProps {
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
onValueChange: ((v: { label: string; value: string }) => void) | null;
|
onValueChange: ((v: { label: string; value: string }) => void) | null;
|
||||||
value: string;
|
value: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
@@ -51,13 +50,13 @@ export function DropdownMenuRadio({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DropdownProps {
|
export interface DropdownProps {
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
items: (
|
items: (
|
||||||
| {
|
| {
|
||||||
label: string;
|
label: string;
|
||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
leftSlot?: ComponentChildren;
|
leftSlot?: ReactNode;
|
||||||
}
|
}
|
||||||
| '-----'
|
| '-----'
|
||||||
)[];
|
)[];
|
||||||
@@ -92,7 +91,7 @@ export function Dropdown({ children, items }: DropdownProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DropdownMenuPortalProps {
|
interface DropdownMenuPortalProps {
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropdownMenuPortal({ children }: DropdownMenuPortalProps) {
|
function DropdownMenuPortal({ children }: DropdownMenuPortalProps) {
|
||||||
@@ -265,7 +264,7 @@ function DropdownMenuSeparator({ className, ...props }: D.DropdownMenuSeparatorP
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DropdownMenuTriggerProps = D.DropdownMenuTriggerProps & {
|
type DropdownMenuTriggerProps = D.DropdownMenuTriggerProps & {
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -278,9 +277,9 @@ function DropdownMenuTrigger({ children, className, ...props }: DropdownMenuTrig
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ItemInnerProps {
|
interface ItemInnerProps {
|
||||||
leftSlot?: ComponentChildren;
|
leftSlot?: ReactNode;
|
||||||
rightSlot?: ComponentChildren;
|
rightSlot?: ReactNode;
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
noHover?: boolean;
|
noHover?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
const colsClasses: Record<string | number, string> = {
|
const colsClasses: Record<string | number, string> = {
|
||||||
none: 'grid-cols-none',
|
none: 'grid-cols-none',
|
||||||
@@ -29,7 +29,7 @@ interface Props {
|
|||||||
cols?: keyof typeof colsClasses;
|
cols?: keyof typeof colsClasses;
|
||||||
gap?: keyof typeof gapClasses;
|
gap?: keyof typeof gapClasses;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: ComponentChildren;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Grid({ className, cols, gap, children }: Props) {
|
export function Grid({ className, cols, gap, children }: Props) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: ComponentChildren;
|
children?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Heading({ className, children, ...props }: Props) {
|
export function Heading({ className, children, ...props }: Props) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { forwardRef } from 'preact/compat';
|
import { forwardRef } from "react";
|
||||||
import type { ButtonProps } from './Button';
|
import type { ButtonProps } from './Button';
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
import type { IconProps } from './Icon';
|
import type { IconProps } from './Icon';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
import type { EditorProps } from './Editor';
|
import type { EditorProps } from './Editor';
|
||||||
import { Editor } from './Editor';
|
import { Editor } from './Editor';
|
||||||
import { HStack, VStack } from './Stacks';
|
import { HStack, VStack } from './Stacks';
|
||||||
@@ -13,8 +13,8 @@ interface Props {
|
|||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
useEditor?: Pick<EditorProps, 'contentType' | 'useTemplating'>;
|
useEditor?: Pick<EditorProps, 'contentType' | 'useTemplating'>;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
leftSlot?: ComponentChildren;
|
leftSlot?: ReactNode;
|
||||||
rightSlot?: ComponentChildren;
|
rightSlot?: ReactNode;
|
||||||
size?: 'sm' | 'md';
|
size?: 'sm' | 'md';
|
||||||
className?: string;
|
className?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
|||||||
23
src-web/components/RouteError.tsx
Normal file
23
src-web/components/RouteError.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as S from '@radix-ui/react-scroll-area';
|
import * as S from '@radix-ui/react-scroll-area';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ function SidebarItem({ request, active }: { request: HttpRequest; active: boolea
|
|||||||
? 'bg-gray-200/70 text-gray-900'
|
? 'bg-gray-200/70 text-gray-900'
|
||||||
: 'text-gray-600 hover:text-gray-800 active:bg-gray-200/30',
|
: '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}
|
contentEditable={editing}
|
||||||
onDoubleClick={() => setEditing(true)}
|
onDoubleClick={() => setEditing(true)}
|
||||||
justify="start"
|
justify="start"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren, ComponentType } from 'preact';
|
import type { ComponentType, ReactNode } from 'react';
|
||||||
import { Children, Fragment } from 'react';
|
import { Children, Fragment } from 'react';
|
||||||
|
|
||||||
const spaceClassesX = {
|
const spaceClassesX = {
|
||||||
@@ -24,7 +24,7 @@ const spaceClassesY = {
|
|||||||
|
|
||||||
interface HStackProps extends BaseStackProps {
|
interface HStackProps extends BaseStackProps {
|
||||||
space?: keyof typeof spaceClassesX;
|
space?: keyof typeof spaceClassesX;
|
||||||
children?: ComponentChildren;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HStack({ className, space, children, ...props }: HStackProps) {
|
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 {
|
export interface VStackProps extends BaseStackProps {
|
||||||
space?: keyof typeof spaceClassesY;
|
space?: keyof typeof spaceClassesY;
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VStack({ className, space, children, ...props }: VStackProps) {
|
export function VStack({ className, space, children, ...props }: VStackProps) {
|
||||||
@@ -83,7 +83,7 @@ interface BaseStackProps {
|
|||||||
alignItems?: 'start' | 'center';
|
alignItems?: 'start' | 'center';
|
||||||
justifyContent?: 'start' | 'center' | 'end';
|
justifyContent?: 'start' | 'center' | 'end';
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: ComponentChildren;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BaseStack({ className, alignItems, justifyContent, children, as }: BaseStackProps) {
|
function BaseStack({ className, alignItems, justifyContent, children, as }: BaseStackProps) {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StatusColor({ statusCode, children }: Props) {
|
export function StatusColor({ statusCode, children }: Props) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as T from '@radix-ui/react-tabs';
|
import * as T from '@radix-ui/react-tabs';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
import { ScrollArea } from './ScrollArea';
|
import { ScrollArea } from './ScrollArea';
|
||||||
@@ -11,10 +11,10 @@ import './Tabs.css';
|
|||||||
interface Props {
|
interface Props {
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
label: string;
|
label: string;
|
||||||
tabs: { value: string; label: ComponentChildren }[];
|
tabs: { value: string; label: ReactNode }[];
|
||||||
tabListClassName?: string;
|
tabListClassName?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Tabs({ defaultValue, label, children, tabs, className, tabListClassName }: Props) {
|
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 {
|
interface TabTriggerProps {
|
||||||
value: string;
|
value: string;
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ export function TabTrigger({ value, children, active }: TabTriggerProps) {
|
|||||||
|
|
||||||
interface TabContentProps {
|
interface TabContentProps {
|
||||||
value: string;
|
value: string;
|
||||||
children: ComponentChildren;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { ComponentChildren } from 'preact';
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: ComponentChildren;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WindowDragRegion({ className, ...props }: Props) {
|
export function WindowDragRegion({ className, ...props }: Props) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { invoke } from '@tauri-apps/api';
|
import { invoke } from '@tauri-apps/api';
|
||||||
import { route } from 'preact-router';
|
import { useNavigate, useNavigation } from 'react-router-dom';
|
||||||
import type { HttpRequest } from '../lib/models';
|
import type { HttpRequest } from '../lib/models';
|
||||||
import { convertDates } from '../lib/models';
|
import { convertDates } from '../lib/models';
|
||||||
import { responsesQueryKey } from './useResponses';
|
import { responsesQueryKey } from './useResponses';
|
||||||
@@ -46,12 +46,12 @@ export function useRequestCreate({
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
navigateAfter: boolean;
|
navigateAfter: boolean;
|
||||||
}) {
|
}) {
|
||||||
|
const navigate = useNavigate();
|
||||||
return useMutation<string, unknown, Pick<HttpRequest, 'name'>>({
|
return useMutation<string, unknown, Pick<HttpRequest, 'name'>>({
|
||||||
mutationFn: async (patch) => invoke('create_request', { ...patch, workspaceId }),
|
mutationFn: async (patch) => invoke('create_request', { ...patch, workspaceId }),
|
||||||
onSuccess: async (requestId) => {
|
onSuccess: async (requestId) => {
|
||||||
console.log('DONE', { requestId, navigateAfter });
|
|
||||||
if (navigateAfter) {
|
if (navigateAfter) {
|
||||||
route(`/workspaces/${workspaceId}/requests/${requestId}`);
|
navigate(`/workspaces/${workspaceId}/requests/${requestId}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { render } from 'preact';
|
import ReactDOM from 'react-dom/client';
|
||||||
import { App } from './App';
|
import { App } from './App';
|
||||||
import { setAppearance } from './lib/theme/window';
|
import { setAppearance } from './lib/theme/window';
|
||||||
import './main.css';
|
import './main.css';
|
||||||
@@ -6,4 +6,4 @@ import './main.css';
|
|||||||
setAppearance();
|
setAppearance();
|
||||||
|
|
||||||
// root holds our app's root DOM Element:
|
// root holds our app's root DOM Element:
|
||||||
render(<App />, document.getElementById('root') as HTMLElement);
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
import { useWindowSize } from 'react-use';
|
import { useWindowSize } from 'react-use';
|
||||||
import { RequestPane } from '../components/RequestPane';
|
import { RequestPane } from '../components/RequestPane';
|
||||||
import { ResponsePane } from '../components/ResponsePane';
|
import { ResponsePane } from '../components/ResponsePane';
|
||||||
@@ -12,10 +13,11 @@ type Params = {
|
|||||||
requestId?: string;
|
requestId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Workspace({ matches }: { path: string; matches?: Params }) {
|
export function Workspace() {
|
||||||
const workspaceId = matches?.workspaceId ?? '';
|
const params = useParams<Params>();
|
||||||
|
const workspaceId = params?.workspaceId ?? '';
|
||||||
const { data: requests } = useRequests(workspaceId);
|
const { data: requests } = useRequests(workspaceId);
|
||||||
const request = requests?.find((r) => r.id === matches?.requestId);
|
const request = requests?.find((r) => r.id === params?.requestId);
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
const isH = width > 900;
|
const isH = width > 900;
|
||||||
|
|
||||||
@@ -24,7 +26,7 @@ export function Workspace({ matches }: { path: string; matches?: Params }) {
|
|||||||
<Sidebar
|
<Sidebar
|
||||||
requests={requests ?? []}
|
requests={requests ?? []}
|
||||||
workspaceId={workspaceId}
|
workspaceId={workspaceId}
|
||||||
activeRequestId={matches?.requestId}
|
activeRequestId={params?.requestId}
|
||||||
/>
|
/>
|
||||||
{request && (
|
{request && (
|
||||||
<div className="grid grid-rows-[auto_minmax(0,1fr)] h-full">
|
<div className="grid grid-rows-[auto_minmax(0,1fr)] h-full">
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ import { Heading } from '../components/Heading';
|
|||||||
import { VStack } from '../components/Stacks';
|
import { VStack } from '../components/Stacks';
|
||||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
export function Workspaces() {
|
||||||
export function Workspaces(props: { path: string }) {
|
|
||||||
const workspaces = useWorkspaces();
|
const workspaces = useWorkspaces();
|
||||||
return (
|
return (
|
||||||
<VStack as="ul" className="p-12">
|
<VStack as="ul" className="p-12">
|
||||||
<Heading>Workspaces</Heading>
|
<Heading>Workspaces</Heading>
|
||||||
{workspaces.data?.map((w) => (
|
{workspaces.data?.map((w) => (
|
||||||
<ButtonLink key={w.id} color="gray" href={`/workspaces/${w.id}`}>
|
<ButtonLink key={w.id} color="gray" to={`/workspaces/${w.id}`}>
|
||||||
{w.name}
|
{w.name}
|
||||||
</ButtonLink>
|
</ButtonLink>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -15,12 +15,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx"
|
||||||
"jsxImportSource": "preact",
|
|
||||||
"paths": {
|
|
||||||
"react": ["./node_modules/preact/compat/"],
|
|
||||||
"react-dom": ["./node_modules/preact/compat/"]
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src-web"
|
"src-web"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import preact from '@preact/preset-vite';
|
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
import topLevelAwait from 'vite-plugin-top-level-await';
|
import topLevelAwait from 'vite-plugin-top-level-await';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
const config = defineConfig({
|
const config = defineConfig({
|
||||||
plugins: [preact({ devToolsEnabled: true }), topLevelAwait()],
|
plugins: [react(), topLevelAwait()],
|
||||||
|
|
||||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||||
// prevent vite from obscuring rust errors
|
// prevent vite from obscuring rust errors
|
||||||
|
|||||||
Reference in New Issue
Block a user