Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to preact #719

Merged
merged 4 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions configuration/vite.unit.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,10 @@ import {defineConfig, configDefaults} from 'vitest/config';
export default defineConfig({
esbuild: {
jsx: 'automatic',
jsxImportSource: 'react',
jsxImportSource: 'preact',
},
resolve: {
conditions: ['quilt:source'],
alias: {
'@quilted/react-testing/matchers': '@quilted/react-testing/matchers',
'@quilted/react-testing': '@quilted/react-testing/preact',
'react/jsx-runtime': 'preact/jsx-runtime',
'react/jsx-dev-runtime': 'preact/jsx-runtime',
react: 'preact/compat',
'react-dom': 'preact/compat',
},
},
test: {
include: ['./**/*.test.ts', './**/*.test.tsx'],
Expand Down
4 changes: 2 additions & 2 deletions documentation/features/async.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ When the application is server-rendered, the JavaScript and CSS needed for the c
Like `useAsyncModule()`, `AsyncComponent` uses suspense to indicate when the module has not yet been loaded. You can include a `Suspense` component to provide a loading state while the component is being fetched:

```tsx
import {Suspense} from 'react';
import {Suspense} from 'preact/compat';
import {AsyncModule, AsyncComponent} from '@quilted/quilt/async';

const returnsModule = new AsyncModule(() => import('./Returns.tsx'));
Expand Down Expand Up @@ -261,7 +261,7 @@ Like asynchronous modules, asynchronous components let you take more fine-graine
To accomplish this, Quilt let’s you specify how the client will render, both on the client and server. If we want to delay when the code for a component is loaded on the client, we can pass the `client: 'defer'` option to our asynchronous component. This will tell the async component to suspend, but not to load the JavaScript for the component immediately. Instead, you are in control of when the JavaScript loads, by calling the asynchronous component’s `load()` method. In the example below, we show delay loading the component until the browser is idle.

```tsx
import {useEffect} from 'react';
import {useEffect} from 'preact/hooks';
import {AsyncComponent} from '@quilted/quilt/async';

const BelowTheFoldComponent = AsyncComponent.from(
Expand Down
26 changes: 13 additions & 13 deletions documentation/features/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ function MyComponent() {
In all of these cases, the values passed to the `to` prop are resolved to a string and used as the `href` prop on the resulting `<a>` element. When the resolved URL is to a separate domain, the component will allow the browser to perform a “normal” full-page navigation; in all other cases, the component will instead perform a navigation with the [history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API), which navigates without a full-page reload. You can force a full-page navigation regardless of the resolved URL by setting the `external` prop to `true`:

```tsx
import {Link} from '@quilted/react-router';
import {Link} from '@quilted/quilt';

function MyComponent() {
return (
Expand All @@ -958,8 +958,8 @@ function MyComponent() {
In addition to the `external` and `to` props, you can also pass any prop (other than `href`) to the `<Link />` component that is supported by the `<a>` element:

```tsx
import type {ComponentProps} from 'react';
import {Link} from '@quilted/react-router';
import type {ComponentProps} from 'preact';
import {Link} from '@quilted/quilt';

// A custom Link that accepts the same props as the `<Link />` component,
// but adds a few custom props that are passed through to the `<a>` element.
Expand Down Expand Up @@ -1268,7 +1268,7 @@ Sometimes, you don’t render a `Link`, but you know you will be navigating to a
In the next example, we’ve added route-based preloading to our programmatic navigation example, so that the list page is already preloaded by the time we delete the product and navigate back to our product list:

```tsx
import {useState} from 'react';
import {useState} from 'preact/hooks';
import {useNavigate, usePreloadRoute} from '@quilted/quilt/navigate';

export function DeleteProductButton({id}: {id: string}) {
Expand Down Expand Up @@ -1477,7 +1477,7 @@ Quilt will default to persisting scroll measurements to [`sessionStorage`](https

```tsx
import {Routing, Link} from '@quilted/quilt/navigate';
import {createMemoryScrollRestoration} from '@quilted/react-router';
import {createMemoryScrollRestoration} from '@quilted/preact-router';

// Some applications may not be able to access `sessionStorage`. This
// helper function creates a scroll restoration strategy that just stores
Expand Down Expand Up @@ -1507,7 +1507,7 @@ function Two() {
If you have a custom scroll container for your app, you can call the `useRouteChangeScrollRestoration()` hook, which provides a [ref](https://reactjs.org/docs/refs-and-the-dom.html) you can use to designate the right element to measure and scroll:

```tsx
import type {PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact';
import {
Routing,
useRouteChangeScrollRestoration,
Expand All @@ -1533,7 +1533,7 @@ function Routes() {
// This component renders a scrollable element to contain the app, so we attach
// the scrollable ref to our element. This prevents the default behavior of
// scrolling the HTML element, which would not do anything in this case.
function Container({children}: PropsWithChildren) {
function Container({children}: RenderableProps<{}>) {
const scrollableRef = useRouteChangeScrollRestoration();

return (
Expand Down Expand Up @@ -1588,7 +1588,7 @@ function Payments() {
The `useRouteChangeScrollRestoration()` hook also allows you to register additional elements on the page whose scroll positions should independently measured and restored when the route changes. Pass a string as the first argument to `useRouteChangeScrollRestoration()`, and that string will be used as a unique identifier for your custom scroll area. You’ll need to use the resulting ref to specify the custom scrollable element — Quilt will only use the HTML element as the default for the “main” scroll restoration.

```tsx
import type {PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact';
import {
Routing,
useRoutes,
Expand All @@ -1612,7 +1612,7 @@ function Routes() {
return <Container>{routes}</Container>;
}

function Container({children}: PropsWithChildren) {
function Container({children}: RenderableProps<{}>) {
const sidePanelScrollRef = useRouteChangeScrollRestoration('SidePanel');

return (
Expand Down Expand Up @@ -1645,7 +1645,7 @@ Quilt’s router defaults to recreating this behavior — after a route change,
You might want to consider adding a [“skip navigation” link](https://webaim.org/techniques/skipnav/) to improve this experience, but you can also tell Quilt to put focus on a more appropriate element after navigation. Quilt provides a `useRouteChangeFocus()` hook that returns a React `ref`. You can attach that `ref` to any DOM node you want to put focus on when the active route changes.

```tsx
import type {PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact';
import {Routing, useRouteChangeFocus, useRoutes} from '@quilted/quilt/navigate';

function App() {
Expand All @@ -1658,7 +1658,7 @@ function App() {
);
}

function Frame({children}: PropsWithChildren) {
function Frame({children}: RenderableProps<{}>) {
const routeChangeFocusRef = useRouteChangeFocus();

return (
Expand Down Expand Up @@ -1696,7 +1696,7 @@ You pass this hook a function that will be called for any navigation that is att
The function you pass to `useNavigationBlock()` is called with an object containing a `targetUrl` property, which is an `EnhancedURL` object representing the target destination, and a `currentUrl` property that indicates the active route in your application. You can use these fields to conditionally block only for some destinations:

```tsx
import {useState} from 'react';
import {useState} from 'preact/hooks';
import {Routing, useNavigationBlock} from '@quilted/quilt/navigate';
import {TextField} from 'some-ui-library';

Expand Down Expand Up @@ -1735,7 +1735,7 @@ The `useNavigationBlock()` hook returns an object with details about the block.
These details are especially useful when using a simplified version of the `useNavigationBlock()` hook, where you provide a boolean argument indicating whether the navigation block is active (or omit the function argument entirely, in which case it defaults to `true`). You can block all navigations conditionally, and use the `blocked` and `unblock` properties to render your own UI

```tsx
import {useState} from 'react';
import {useState} from 'preact/hooks';
import {Routing, useNavigationBlock} from '@quilted/quilt/navigate';
import {TextField, Dialog} from 'my-ui-library';

Expand Down
10 changes: 6 additions & 4 deletions documentation/integrations/trpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ The basic app renders a number of “global” context providers in the main `ap
```tsx
// app/App.tsx

import {useMemo, type PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact';
import {useMemo} from 'preact/hooks';
import {useInitialUrl} from '@quilted/quilt/navigate';

import {httpBatchLink} from '@trpc/client';
Expand All @@ -130,7 +131,7 @@ export default function App() {

interface TrpcProps {}

function Trpc({children}: PropsWithChildren<TrpcProps>) {
function Trpc({children}: RenderableProps<TrpcProps>) {
const initialUrl = useInitialUrl();

const queryClient = useMemo(() => new QueryClient(), []);
Expand Down Expand Up @@ -190,7 +191,8 @@ To use this optimization, you’ll need to accept a different tRPC link when ser
```tsx
// app/App.tsx

import {useMemo, type PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact';
import {useMemo} from 'preact/hooks';
import {useInitialUrl} from '@quilted/quilt/navigate';

import {httpBatchLink, type TRPCClient} from '@trpc/client';
Expand Down Expand Up @@ -220,7 +222,7 @@ interface TrpcProps {
client?: TRPCClient<any>;
}

function Trpc({client, children}: PropsWithChildren<TrpcProps>) {
function Trpc({client, children}: RenderableProps<TrpcProps>) {
const initialUrl = useInitialUrl();

const queryClient = useMemo(() => new QueryClient(), []);
Expand Down
5 changes: 3 additions & 2 deletions documentation/integrations/web-vitals.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ Each template app comes with an `Observability` component. This component is loc
Find your metrics `Metrics` component, and add the Core Web Vitals listeners for the metrics you want to track in a `useEffect` hook:

```tsx
import {useEffect, type PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact/hooks';
import {useEffect} from 'preact/hooks';
import {onLCP, onFID, onCLS, type Metric} from 'web-vitals';

import {usePerformanceNavigationEvent} from '@quilted/quilt/navigation';

export function Observability({children}: PropsWithChildren) {
export function Observability({children}: RenderableProps<{}>) {
useEffect(() => {
onLCP(handleMetric);
onFID(handleMetric);
Expand Down
6 changes: 3 additions & 3 deletions documentation/projects/apps/browser.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@ import '@quilted/quilt/globals';
import {ErrorLogging} from 'my-error-logging-library/browser';

// If you are not server rendering, swap this out with `renderRoot` instead
import {hydrateRoot} from 'react-dom/client';
import {hydrate} from 'preact';

import App from './App.tsx';

ErrorLogging.start();

const element = document.querySelector('#root')!;
const element = document.querySelector('#app')!;

hydrateRoot(element, <App />);
hydrate(<App />, element);
```

### Dependency bundles
Expand Down
2 changes: 1 addition & 1 deletion integrations/react-query/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ $ pnpm add @quilted/react-query @tanstack/react-query --save
[React Query’s getting started instructions](https://tanstack.com/query/v4/docs/quick-start) instruct you to create a `QueryClient` object, and pass it to a `QueryClientProvider` component. To integrate React Query with Quilt, you will pass your `QueryClient` object to this library’s `ReactQueryContext` component instead:

```tsx
import {useMemo} from 'react';
import {useMemo} from 'preact/hooks';
import {QueryClient} from '@tanstack/react-query';
import {ReactQueryContext} from '@quilted/react-query';

Expand Down
12 changes: 6 additions & 6 deletions integrations/react-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@
},
"peerDependencies": {
"@quilted/quilt": "workspace:^0.6.16",
"react": "^17.0.0 || ^18.0.0",
"@tanstack/react-query": "^5.0.0"
"@tanstack/react-query": "^5.0.0",
"preact": "^10.21.0"
},
"devDependencies": {
"@quilted/quilt": "workspace:^",
"@quilted/quilt": "workspace:*",
"@tanstack/react-query": "^5.34.1",
"react": "workspace:@quilted/react@^18.2.0"
},
"peerDependenciesMeta": {
"@quilted/quilt": {
"optional": true
},
"react": {
"optional": true
},
"@tanstack/react-query": {
"optional": false
},
"preact": {
"optional": true
}
}
}
23 changes: 17 additions & 6 deletions integrations/react-query/source/ReactQueryContext.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
import type {PropsWithChildren} from 'react';
import type {RenderableProps, ComponentType} from 'preact';
import {
QueryClientProvider,
QueryClient,
dehydrate,
HydrationBoundary,
QueryClient,
QueryClientProvider as QueryClientProviderReact,
type QueryClientProviderProps,
HydrationBoundary as HydrationBoundaryReact,
type HydrationBoundaryProps,
type DehydratedState,
} from '@tanstack/react-query';
import {useSerialized} from '@quilted/quilt/browser';
import {Serialize} from '@quilted/quilt/server';

const SERIALIZATION_ID = 'quilt:react-query';

const HydrationBoundary = HydrationBoundaryReact as ComponentType<
Omit<HydrationBoundaryProps, 'children'>
>;
const QueryClientProvider = QueryClientProviderReact as ComponentType<
Omit<QueryClientProviderProps, 'children'>
>;

export function ReactQueryContext({
client,
children,
}: PropsWithChildren<{client: QueryClient}>) {
}: RenderableProps<{client: QueryClient}>) {
const dehydratedState = useSerialized<DehydratedState | undefined>(
SERIALIZATION_ID,
);

return (
<QueryClientProvider client={client}>
<HydrationBoundary state={dehydratedState}>{children}</HydrationBoundary>
<HydrationBoundary state={dehydratedState}>
{children as any}
</HydrationBoundary>
<Serializer client={client} />
</QueryClientProvider>
);
Expand Down
2 changes: 1 addition & 1 deletion integrations/react-query/source/use-graphql-mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function useGraphQLMutation<Data, Variables>(
...reactMutationOptions
}: GraphQLMutationOptions<Data, Variables> = {},
): UseMutationResult<Data, unknown, Variables> {
const fetchFromContext = useGraphQLFetch({required: false});
const fetchFromContext = useGraphQLFetch({optional: true});
const fetch = explicitFetch ?? fetchFromContext;

if (fetch == null) {
Expand Down
2 changes: 1 addition & 1 deletion integrations/react-query/source/use-graphql-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function useGraphQLQuery<Data, Variables>(
...reactQueryOptions
} = options as GraphQLQueryOptions<Data, Variables>;

const fetchFromContext = useGraphQLFetch({required: false});
const fetchFromContext = useGraphQLFetch({optional: true});
const fetch = explicitFetch ?? fetchFromContext;

if (fetch == null) {
Expand Down
3 changes: 2 additions & 1 deletion integrations/react-query/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"extends": "@quilted/typescript/tsconfig.project.json",
"compilerOptions": {
"rootDir": "source",
"outDir": "build/typescript"
"outDir": "build/typescript",
"jsxImportSource": "preact"
},
"include": ["source"],
"exclude": ["**/*.test.ts", "**/*.test.tsx"],
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@
"jsdom": "^24.0.0",
"preact": "^10.21.0",
"prettier": "^3.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rollup": "^4.14.0",
"source-map-support": "^0.5.0",
"tsx": "^4.7.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/babel/source/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface State {

const DEFAULT_PACKAGES_TO_PROCESS = {
'@quilted/async': ['AsyncModule', 'AsyncComponent'],
'@quilted/react-async': ['AsyncModule', 'AsyncComponent'],
'@quilted/preact-async': ['AsyncModule', 'AsyncComponent'],
'@quilted/quilt/async': ['AsyncModule', 'AsyncComponent'],
};

Expand Down
2 changes: 1 addition & 1 deletion packages/babel/source/workers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface WorkerWrapper {

const DEFAULT_PACKAGES_TO_PROCESS = {
'@quilted/workers': ['createWorker', 'createThreadWorker'],
'@quilted/react-workers': ['createWorker', 'createThreadWorker'],
'@quilted/preact-workers': ['createWorker', 'createThreadWorker'],
'@quilted/quilt/threads': ['createWorker', 'createThreadWorker'],
};

Expand Down
2 changes: 1 addition & 1 deletion packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"repository": {
"type": "git",
"url": "https://github.com/lemonmade/quilt.git",
"directory": "packages/react-browser"
"directory": "packages/browser"
},
"exports": {
".": {
Expand Down
4 changes: 2 additions & 2 deletions packages/create/templates/app-basic/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type PropsWithChildren} from 'react';
import type {RenderableProps} from 'preact';

import {Routing, useRoutes} from '@quilted/quilt/navigate';
import {Localization, useLocaleFromEnvironment} from '@quilted/quilt/localize';
Expand Down Expand Up @@ -42,7 +42,7 @@ function Routes() {
}

// This component renders any app-wide context.
function AppContext({children, context}: PropsWithChildren<AppProps>) {
function AppContext({children, context}: RenderableProps<AppProps>) {
const locale = useLocaleFromEnvironment() ?? 'en';

return (
Expand Down
Loading
Loading