Back to React

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

721
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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.

View File

@@ -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>
); );
} }

View File

@@ -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>
);
}
}); });

View File

@@ -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}
/>
); );
} }

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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';

View File

@@ -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;

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 * 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;
} }

View File

@@ -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"

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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;
} }

View File

@@ -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) {

View File

@@ -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}`);
} }
}, },
}); });

View File

@@ -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 />);

View File

@@ -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">

View File

@@ -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>
))} ))}

View File

@@ -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"

View File

@@ -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