diff --git a/.changeset/wild-moose-dream.md b/.changeset/wild-moose-dream.md new file mode 100644 index 000000000..429d74734 --- /dev/null +++ b/.changeset/wild-moose-dream.md @@ -0,0 +1,6 @@ +--- +'@quilted/preact-browser': patch +'@quilted/create': patch +--- + +Make browser context creation implicit on the client diff --git a/packages/create/templates/app-basic/browser.tsx b/packages/create/templates/app-basic/browser.tsx index 33ee7220d..c5c484971 100644 --- a/packages/create/templates/app-basic/browser.tsx +++ b/packages/create/templates/app-basic/browser.tsx @@ -1,24 +1,15 @@ import '@quilted/quilt/globals'; -import {hydrate} from 'preact'; -import {Browser, BrowserContext} from '@quilted/quilt/browser'; +import {hydrate} from '@quilted/quilt/browser'; import {Router} from '@quilted/quilt/navigation'; import type {AppContext} from '~/shared/context.ts'; import {App} from './App.tsx'; -const element = document.querySelector('#app')!; -const browser = new Browser(); - const context = { - router: new Router(browser.request.url), + router: new Router(), } satisfies AppContext; // Makes key parts of the app available in the browser console Object.assign(globalThis, {app: context}); -hydrate( - - - , - element, -); +hydrate(); diff --git a/packages/create/templates/app-basic/tests/render/render.tsx b/packages/create/templates/app-basic/tests/render/render.tsx index 46bcddef3..5a2c742c2 100644 --- a/packages/create/templates/app-basic/tests/render/render.tsx +++ b/packages/create/templates/app-basic/tests/render/render.tsx @@ -1,5 +1,8 @@ import {createRender} from '@quilted/quilt/testing'; -import {BrowserContext, BrowserTestMock} from '@quilted/quilt/browser/testing'; +import { + BrowserDetailsContext, + BrowserTestMock, +} from '@quilted/quilt/browser/testing'; import {Navigation, TestRouter} from '@quilted/quilt/navigation/testing'; import {Localization} from '@quilted/quilt/localize'; @@ -29,11 +32,11 @@ export const renderApp = createRender< return ( - + {element} - + ); }, diff --git a/packages/create/templates/app-graphql/browser.tsx b/packages/create/templates/app-graphql/browser.tsx index dcc712427..ec9f43fbd 100644 --- a/packages/create/templates/app-graphql/browser.tsx +++ b/packages/create/templates/app-graphql/browser.tsx @@ -1,22 +1,18 @@ import '@quilted/quilt/globals'; -import {hydrate} from 'preact'; -import {createGraphQLFetch, GraphQLCache} from '@quilted/quilt/graphql'; -import {Browser, BrowserContext} from '@quilted/quilt/browser'; +import {hydrate} from '@quilted/quilt/browser'; import {Router} from '@quilted/quilt/navigation'; +import {createGraphQLFetch, GraphQLCache} from '@quilted/quilt/graphql'; import type {AppContext} from '~/shared/context.ts'; import {App} from './App.tsx'; -const element = document.querySelector('#app')!; -const browser = new Browser(); - const graphQLFetch = createGraphQLFetch({url: '/api/graphql'}); const graphQLCache = new GraphQLCache({fetch: graphQLFetch}); const context = { - router: new Router(browser.request.url), + router: new Router(), graphql: { fetch: graphQLFetch, cache: graphQLCache, @@ -26,9 +22,4 @@ const context = { // Makes key parts of the app available in the browser console Object.assign(globalThis, {app: context}); -hydrate( - - - , - element, -); +hydrate(); diff --git a/packages/create/templates/app-graphql/tests/render/render.tsx b/packages/create/templates/app-graphql/tests/render/render.tsx index e9bf3da36..dbd63abd9 100644 --- a/packages/create/templates/app-graphql/tests/render/render.tsx +++ b/packages/create/templates/app-graphql/tests/render/render.tsx @@ -1,7 +1,10 @@ import {Suspense} from 'preact/compat'; import {createRender} from '@quilted/quilt/testing'; -import {BrowserContext, BrowserTestMock} from '@quilted/quilt/browser/testing'; +import { + BrowserDetailsContext, + BrowserTestMock, +} from '@quilted/quilt/browser/testing'; import {Navigation, TestRouter} from '@quilted/quilt/navigation/testing'; import {Localization} from '@quilted/quilt/localize'; import {GraphQLCache} from '@quilted/quilt/graphql'; @@ -44,7 +47,7 @@ export const renderApp = createRender< return ( - + - + ); }, diff --git a/packages/create/templates/app-trpc/browser.tsx b/packages/create/templates/app-trpc/browser.tsx index 7a0f8e28b..32c74a2ab 100644 --- a/packages/create/templates/app-trpc/browser.tsx +++ b/packages/create/templates/app-trpc/browser.tsx @@ -1,26 +1,23 @@ import '@quilted/quilt/globals'; -import {hydrate} from 'preact'; +import {hydrate} from '@quilted/quilt/browser'; +import {Router} from '@quilted/quilt/navigation'; + import {httpBatchLink} from '@trpc/client'; import {QueryClient} from '@tanstack/react-query'; -import {Browser, BrowserContext} from '@quilted/quilt/browser'; -import {Router} from '@quilted/quilt/navigation'; import type {AppContext} from '~/shared/context.ts'; import {trpc} from '~/shared/trpc.ts'; import {App} from './App.tsx'; -const element = document.querySelector('#app')!; -const browser = new Browser(); - const queryClient = new QueryClient(); const trpcClient = trpc.createClient({ links: [httpBatchLink({url: new URL('/api', window.location.href).href})], }); const context = { - router: new Router(browser.request.url), + router: new Router(), trpc: trpcClient, queryClient, } satisfies AppContext; @@ -28,9 +25,4 @@ const context = { // Makes key parts of the app available in the browser console Object.assign(globalThis, {app: context}); -hydrate( - - - , - element, -); +hydrate(); diff --git a/packages/create/templates/app-trpc/tests/render/render.tsx b/packages/create/templates/app-trpc/tests/render/render.tsx index a05eefff4..3da113aa5 100644 --- a/packages/create/templates/app-trpc/tests/render/render.tsx +++ b/packages/create/templates/app-trpc/tests/render/render.tsx @@ -1,5 +1,8 @@ import {createRender} from '@quilted/quilt/testing'; -import {BrowserContext, BrowserTestMock} from '@quilted/quilt/browser/testing'; +import { + BrowserDetailsContext, + BrowserTestMock, +} from '@quilted/quilt/browser/testing'; import {Navigation, TestRouter} from '@quilted/quilt/navigation/testing'; import {Localization} from '@quilted/quilt/localize'; @@ -37,7 +40,7 @@ export const renderApp = createRender< return ( - + @@ -47,7 +50,7 @@ export const renderApp = createRender< - + ); }, diff --git a/packages/preact-browser/source/browser.tsx b/packages/preact-browser/source/browser.tsx new file mode 100644 index 000000000..1dd023250 --- /dev/null +++ b/packages/preact-browser/source/browser.tsx @@ -0,0 +1,49 @@ +import { + hydrate as preactHydrate, + render as preactRender, + type ComponentChild, +} from 'preact'; + +import {Browser} from '@quilted/browser'; + +import {BrowserDetailsContext} from './context.ts'; + +export function render( + component: ComponentChild, + {element}: {element?: string | Element} = {}, +) { + const browser = new Browser(); + + return preactRender( + + {component} + , + resolveContainerNode(element), + ); +} + +export function hydrate( + component: ComponentChild, + {element}: {element?: string | Element} = {}, +) { + const browser = new Browser(); + + return preactHydrate( + + {component} + , + resolveContainerNode(element), + ); +} + +function resolveContainerNode(selectorOrElement: string | Element = '#app') { + if (typeof selectorOrElement !== 'string') return selectorOrElement; + + const element = document.querySelector(selectorOrElement); + + if (element == null) { + throw new Error(`No element found for selector: ${selectorOrElement}`); + } + + return element; +} diff --git a/packages/preact-browser/source/components/BrowserContext.tsx b/packages/preact-browser/source/components/BrowserContext.tsx deleted file mode 100644 index 1d98fe6f8..000000000 --- a/packages/preact-browser/source/components/BrowserContext.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type {RenderableProps} from 'preact'; -import type {BrowserDetails} from '@quilted/browser'; -import {BrowserDetailsContext} from '../context.ts'; - -/** - * Provides details about the browser to your React app. - */ -export function BrowserContext({ - browser, - children, -}: RenderableProps<{browser: BrowserDetails}>) { - return ( - - {children} - - ); -} diff --git a/packages/preact-browser/source/index.ts b/packages/preact-browser/source/index.ts index 44db01eb6..f7ff65854 100644 --- a/packages/preact-browser/source/index.ts +++ b/packages/preact-browser/source/index.ts @@ -1,5 +1,6 @@ export * from '@quilted/browser'; +export {render, hydrate} from './browser.tsx'; export {BrowserDetailsContext, useBrowserDetails} from './context.ts'; export {useAlternateUrl} from './hooks/alternate-url.ts'; @@ -17,7 +18,6 @@ export {useThemeColor} from './hooks/theme-color.ts'; export {useTitle} from './hooks/title.ts'; export {Alternate} from './components/Alternate.tsx'; -export {BrowserContext} from './components/BrowserContext.tsx'; export {BodyAttributes} from './components/BodyAttributes.tsx'; export {HTMLAttributes} from './components/HTMLAttributes.tsx'; export {Link} from './components/Link.tsx'; diff --git a/packages/preact-browser/source/testing.ts b/packages/preact-browser/source/testing.ts index 672c8dff7..fc2f73fea 100644 --- a/packages/preact-browser/source/testing.ts +++ b/packages/preact-browser/source/testing.ts @@ -1,2 +1,2 @@ export * from '@quilted/browser/testing'; -export {BrowserContext} from './components/BrowserContext.tsx'; +export {BrowserDetailsContext} from './context.ts'; diff --git a/tests/e2e/fixtures/basic-app/browser.tsx b/tests/e2e/fixtures/basic-app/browser.tsx index aca1fc678..5d3eeb88d 100644 --- a/tests/e2e/fixtures/basic-app/browser.tsx +++ b/tests/e2e/fixtures/basic-app/browser.tsx @@ -1,15 +1,6 @@ import '@quilted/quilt/globals'; -import {hydrate} from 'preact'; -import {Browser, BrowserContext} from '@quilted/quilt/browser'; +import {hydrate} from '@quilted/quilt/browser'; import App from './App.tsx'; -const element = document.querySelector('#app')!; -const browser = new Browser(); - -hydrate( - - - , - element, -); +hydrate(); diff --git a/tests/e2e/integrations/trpc.test.ts b/tests/e2e/integrations/trpc.test.ts index d183e865c..da68170f3 100644 --- a/tests/e2e/integrations/trpc.test.ts +++ b/tests/e2e/integrations/trpc.test.ts @@ -58,20 +58,18 @@ describe('trpc', () => { `, 'browser.tsx': multiline` import '@quilted/quilt/globals'; - import {hydrate} from 'preact'; - import {Browser, BrowserContext} from '@quilted/quilt/browser'; + import {hydrate} from '@quilted/quilt/browser'; import {httpBatchLink} from '@trpc/client'; import {QueryClient} from '@tanstack/react-query'; import {App, trpc} from './App.tsx'; const element = document.querySelector('#app')!; - const browser = new Browser(); const trpcClient = trpc.createClient({ links: [ httpBatchLink({ - url: new URL('/api', browser.request.url).href, + url: new URL('/api').href, }), ], }); @@ -79,10 +77,7 @@ describe('trpc', () => { const queryClient = new QueryClient(); hydrate( - - - , - element, + , ); `, 'server.tsx': multiline`