@jhxdev/express 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 nick-hio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,571 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nick-hio/jhx/main/assets/jhx-logo-light.svg">
4
+ <img src="https://raw.githubusercontent.com/nick-hio/jhx/main/assets/jhx-logo-dark.svg" height="90" alt="Logo for jhx">
5
+ </picture>
6
+ </p>
7
+
8
+ <div align="center">
9
+ Type-Safe HTMX.
10
+ </div>
11
+
12
+ <div align="center">
13
+ <a target="_blank" href="https://github.com/nick-hio/jhx">GitHub</a> •
14
+ <a target="_blank" href="https://github.com/nick-hio/jhx">Documentation</a> •
15
+ <a target="_blank" href="https://github.com/nick-hio/jhx/issues/new">Report an Issue</a>
16
+ </div>
17
+
18
+ # @jhxdev/express
19
+
20
+ - **Defines HTMX handlers inline within elements.**
21
+ Creates server endpoints for HTMX interactions without manually configuring routes.
22
+ - **HTMX helper for React/JSX, HTML, and SSR/edge.**
23
+ Dedicated types with strong inference for HTMX patterns, features, and extensions.
24
+ - **Type-safe HTMX attribute and event mapping.**
25
+ Converts typed props into valid HTMX `hx-*` attributes for templating.
26
+ - **Streamlines developer experience for complex HTMX applications.**
27
+ Simplifies the development of large HTMX applications with advanced interactions.
28
+
29
+ > Don't need server integration? **Check out the core package:**
30
+ >
31
+ > - [`jhx`](https://github.com/nick-hio/jhx/tree/main/packages/jhx)
32
+
33
+ ## Table of Contents
34
+
35
+ - [Installation](#installation)
36
+ - [Quick Start](#quick-start)
37
+ - [API](#api)
38
+ - [`createJhx`](#createjhx)
39
+ - [`jhx`](#jhx)
40
+ - [`JhxComponent`](#jhxcomponent)
41
+ - [Examples](#examples)
42
+ - [Default `stringify`](#default-stringify)
43
+ - [Reusing Handlers](#reusing-handlers)
44
+ - [Multiple Instances](#multiple-instances)
45
+ - [Custom `render` Handler](#custom-render-handler)
46
+ - [Custom `middleware` Handler(s)](#custom-middleware-handlers)
47
+ - [Predefined `routes`](#predefined-routes)
48
+ - [DOM Interactions & Type Safety](#dom-interactions--type-safety)
49
+
50
+ ## Installation
51
+
52
+ Install via your preferred package manager:
53
+
54
+ ```
55
+ pnpm install @jhxdev/express
56
+ npm install @jhxdev/express
57
+ bun add @jhxdev/express
58
+ yarn add @jhxdev/express
59
+ ```
60
+
61
+ Import the package:
62
+
63
+ ```ts
64
+ // ESM import
65
+ import { createJhx } from '@jhxdev/express';
66
+
67
+ // CJS import
68
+ const { createJhx } = require('@jhxdev/express');
69
+ ```
70
+
71
+ ## Quick Start
72
+
73
+ Call the `createJhx` function with your Express instance:
74
+
75
+ ```jsx
76
+ import express from 'express';
77
+ import { createJhx } from '@jhxdev/express';
78
+
79
+ const app = express();
80
+ const { jhx, JhxComponent } = createJhx(app);
81
+ ```
82
+
83
+ Create HTMX attributes for JSX props:
84
+
85
+ ```jsx
86
+ const attrs = jhx({
87
+ get: '/api',
88
+ target: '#container',
89
+ });
90
+
91
+ const Button = () => (<button {...attrs}>Load Data</button>);
92
+ // <button hx-get="/_jhx/api" hx-target="#container">Load Data</button>
93
+ ```
94
+
95
+ Create HTMX attributes as a string for HTML and with a generated endpoint:
96
+
97
+ ```jsx
98
+ const attrs = jhx({
99
+ method: 'put', // set the method (defaults to 'get')
100
+ target: '#container',
101
+ handler: () => {
102
+ return `<div>DATA</div>`;
103
+ },
104
+ }, { stringify: true }); // set 'stringify' to 'true'
105
+
106
+ const button = `<button ${attrs}>Load Data</button>`;
107
+ // <button hx-put="/_jhx/<UNIQUE_ID>" hx-target="#container">Load Data</button>
108
+ ```
109
+
110
+ Create HTMX attributes using the JSX component:
111
+
112
+ ```jsx
113
+ const button = (
114
+ <JhxComponent
115
+ as='button' // set the element tag (defaults to 'div')
116
+ post='/api'
117
+ target='#container'
118
+ handler={async () => {
119
+ return `<div>${await db.getData()}</div>`;
120
+ }}
121
+ >
122
+ Load Data
123
+ </JhxComponent>
124
+ );
125
+ // <button hx-post="/_jhx/api" hx-target="#container">Load Data</button>
126
+ ```
127
+
128
+ ## API
129
+
130
+ > See the [Examples](#examples) section for usage.
131
+
132
+ Documentation for the `jhx` and `JhxComponent` APIs can be found in the [`jhx` repository](https://github.com/nick-hio/jhx/tree/main/packages/jhx#api).
133
+
134
+ ### `createJhx`
135
+
136
+ Function which creates instances of `jhx` and `JhxComponent` bound to an Express instance.
137
+
138
+ ```ts
139
+ function createJhx<TDomBase, TError, TReturn, TRequest, TReply>(
140
+ express: Express,
141
+ config?: CreateJhxConfig<TReturn, TError, JhxRenderReturn, TRequest, TReply>,
142
+ ): {
143
+ jhx: Jhx<TDomBase, TReturn, TRequest, TReply>;
144
+ JhxComponent: JhxComponentType<TDomBase, TReturn, TRequest, TReply>;
145
+ };
146
+ ```
147
+
148
+ #### Parameters
149
+
150
+ ##### `express`
151
+
152
+ An Express instance to bind the `jhx` function and `JhxComponent`.
153
+
154
+ ##### `config` (optional)
155
+
156
+ Configuration options for controlling the behavior of `jhx` and `JhxComponent`.
157
+
158
+ | Property | Type | Description |
159
+ |--------------------|-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
160
+ | `contentType` | `string \| false` | Specifies the default `Content-Type` header for responses. Defaults to `text/html`.<br>- When `false`, no default header is used. |
161
+ | `debug` | `boolean` | Enables debug mode for logging additional information. Defaults to `false`. |
162
+ | `errorHandler` | `JhxErrorHandler` | Error handler function which is executed when a middleware or route handler throws an error. |
163
+ | `middleware` | `JhxHandler \| Array<JhxHandler>` | Middleware handler function(s) to execute before the route handler. |
164
+ | `notFoundHandler` | `JhxHandler` | Handler function which is executed when a request does not match any route. |
165
+ | `onRegistered` | `JhxOnRegistered` | Callback function executed when a route is registered. |
166
+ | `prefix` | `string` | Prefix to prepend to all routes. Defaults to `/_jhx`. |
167
+ | `renderError` | `boolean` | Whether to execute the `render` function with the error handler return value. Defaults to `true`. |
168
+ | `renderMiddleware` | `boolean` | Whether to execute the `render` function when a middleware handler returns a value. Defaults to `true`. |
169
+ | `renderNotFound` | `boolean` | Whether to execute the `render` function with the not-found handler return value. Defaults to `true`. |
170
+ | `render` | `JhxRenderHandler \| 'static' \| 'string' \| false` | Determines how responses are rendered before being sent. Allows custom `JhxRenderHandler` function. Defaults to `'string'`.<br>- When `'string'`, **JSX payloads are rendered** using the `renderToString` function from React.<br>- When `'static'`, **JSX payloads are rendered** using the `renderToStaticMarkup` function from React.<br>- When `false`, no render function is executed and all payloads are sent directly. |
171
+ | `routes` | `JhxPartialRoute \| Array<JhxPartialRoute>` | Predefined routes to register with the Express instance upon initialization. |
172
+ | `trailingSlash` | `'slash' \| 'no-slash' \| 'both'` | Controls how to handle trailing slashes in routes. Defaults to `'both'`.<br>- When `'slash'`, routes will **only accept** trailing slashes (e.g., `/api/`). <br>- When `'no-slash'`, routes will **not accept** trailing slashes (e.g., `/api`). <br>- When `'both'`, routes will **accept both** (e.g., `/api` or `/api/`). |
173
+
174
+ #### Generics
175
+
176
+ - `TDom` (extends `object`) - Type for the additional DOM variables (see the [DOM Interactions & Type Safety](#dom-interactions--type-safety) section for usage).
177
+ - `TError` (extends `JhxErrorType`) - Type for the error value passed to the error handler.
178
+ - `TReturn` (extends `JhxHandlerReturn`) - Type for the return value of the handler functions.
179
+ - `TRequest` (extends `Request` from Express) - Type for the Express request object.
180
+ - `TResponse` (extends `Response` from Express) - Type for the Express response object.
181
+
182
+ #### Returns
183
+
184
+ The `createJhx` function returns an object containing the following properties:
185
+ - `jhx` - An extended `jhx` function which is bound to the Express instance through the `handler` prop.
186
+ - `JhxComponent` - An extended `JhxComponent` which is bound to the Express instance through the `handler` prop.
187
+
188
+ ### `jhx`
189
+
190
+ A function that transforms props into an object of HTMX attributes and registers the corresponding route handler.
191
+
192
+ ```ts
193
+ function jhx<TDom>(props: JhxDomProps<TDom>, config?: JhxConfig & { stringify: true }): string;
194
+ function jhx<TDom>(props: JhxProps<TDom>, config?: JhxConfig & { stringify?: false }): Record<JhxAttribute, string>;
195
+ ```
196
+
197
+ #### Parameters
198
+
199
+ ##### `props`
200
+
201
+ An object containing the HTMX attribute values and the route handler function.
202
+
203
+ | Property | Type | Description |
204
+ |------------------------------|------------------------------------------------------------------------------------------------------------|-----------------------------------------------|
205
+ | `handler` | `JhxHandler` | Route handler function for the HTMX endpoint. |
206
+ | All props for the base `jhx` | See the [`jhx` repository](https://github.com/nick-hio/jhx/tree/main/packages/jhx#props) for more details. | All other HTMX-related props. |
207
+
208
+ ##### `config` (optional)
209
+
210
+ Configuration options for the function.
211
+
212
+ | Property | Type | Description |
213
+ |-------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
214
+ | `escape` | `boolean` | Whether to escape the HTML characters in the attribute values. Defaults to `true`. |
215
+ | `logger` | `Logger` | Logging functions for debug messages, warnings, and errors from jhx. Defaults to `console`. |
216
+ | `stringify` | `boolean` | Converts the result into a string of HTML attributes. Overrides the default value. Defaults to `false`.<br>- When `true`, returns a string of HTML attributes.<br>- When `false`, returns an object for JSX spreading. |
217
+
218
+ #### Generics
219
+
220
+ - `TDom` (extends `object`) - Type for the additional DOM variables (see the [DOM Interactions & Type Safety](#dom-interactions--type-safety) section for usage).
221
+
222
+ #### Returns
223
+
224
+ `jhx` will return a `string` when `config.stringify` set to `true`, otherwise, returns a `Record<JhxAttribute, string>`.
225
+
226
+ #### Utility Functions
227
+
228
+ Each `jhx` function instance has the following functions to help with managing its routes:
229
+
230
+ - `addRoute` - Registers a single route. Automatically prepends the `config.prefix` value from initialization.
231
+ ```ts
232
+ jhx.addRoute({ route: string, method: string, handler: JhxHandler }): void;
233
+ ```
234
+
235
+ - `addRoutes` - Registers multiple routes. Automatically prepends the `config.prefix` value from initialization.
236
+ ```ts
237
+ jhx.addRoutes(Array<{ route: string, method: string, handler: JhxHandler }>): void;
238
+ ```
239
+
240
+ - `clearRoutes` - Removes all registered routes.
241
+ ```ts
242
+ jhx.clearRoutes(): void;
243
+ ```
244
+
245
+ - `getRoute` - Returns the configuration for a specific route. Returns `null` when the route doesn't exist.
246
+ ```ts
247
+ jhx.getRoute({ route: string, method: string }): { route: string, method: HttpMethod, handler: JhxHandler } | null;
248
+ ```
249
+
250
+ - `getRoutes` - Returns an array of all registered routes and their configurations.
251
+ ```ts
252
+ jhx.getRoutes(): Array<{ route: string, method: HttpMethod, handler: JhxHandler }>;
253
+ ```
254
+
255
+ - `hasRoute` - Checks if a specific route is registered.
256
+ ```ts
257
+ jhx.hasRoute({ route: string, method: string }): boolean;
258
+ ```
259
+
260
+ - `removeRoute` - Removes a specific route. Returns a `true` when the route was removed, otherwise `false`.
261
+ ```ts
262
+ jhx.removeRoute({ route: string, method: string }): boolean;
263
+ ```
264
+
265
+ ### `JhxComponent`
266
+
267
+ JSX wrapper element for the `jhx` function bound to the Express instance.
268
+
269
+ ```ts
270
+ function JhxComponent<TDom>(props: PropsWithChildren<JhxComponentProps<TDom>>): JSX.Element
271
+ ```
272
+
273
+ #### Props
274
+
275
+ | Prop | Type | Description |
276
+ |---------------------|--------------------------------|-----------------------------------------------------------------------------------------|
277
+ | `as` | `keyof JSX.IntrinsicElements` | Specifies the element tag for the component. Defaults to `div`. |
278
+ | `jhxConfig` | `Omit<JhxConfig, 'stringify'>` | Configuration options passed to the `jhx` function, excluding the `stringify` property. |
279
+ | All props for `jhx` | See the [`jhx`](#jhx) section | Props passed to the wrapped `jhx` function. |
280
+
281
+ #### Generics
282
+
283
+ - `TDom` (extends `object`) - Type for the additional DOM variables (see the [DOM Interactions & Type Safety](#dom-interactions--type-safety) section for usage).
284
+
285
+ ## Examples
286
+
287
+ - [Default `stringify`](#default-stringify)
288
+ - [Reusing Handlers](#reusing-handlers)
289
+ - [Multiple Instances](#multiple-instances)
290
+ - [Custom `render` Handler](#custom-render-handler)
291
+ - [Custom `middleware` Handlers](#custom-middleware-handlers)
292
+ - [Predefined `routes`](#predefined-routes)
293
+ - [DOM Interactions & Type Safety](#dom-interactions--type-safety)
294
+
295
+ > See additional examples in the [`jhx` repository](https://github.com/nick-hio/jhx/tree/main/packages/jhx):
296
+ >
297
+ > - [Setting the Request Method](https://github.com/nick-hio/jhx/tree/main/packages/jhx#setting-the-request-method)
298
+ > - [`jhx` in JSX (Object Output)](https://github.com/nick-hio/jhx/tree/main/packages/jhx#jhx-in-jsx-object-output)
299
+ > - [`jhx` in HTML (String Output)](https://github.com/nick-hio/jhx/tree/main/packages/jhx#jhx-in-html-string-output)
300
+ > - [`JhxComponent` in JSX](https://github.com/nick-hio/jhx/tree/main/packages/jhx#jhxcomponent-in-jsx)
301
+ > - [HTMX & DOM Events](https://github.com/nick-hio/jhx/tree/main/packages/jhx#htmx--dom-events)
302
+ > - [Advanced Props](https://github.com/nick-hio/jhx/tree/main/packages/jhx#advanced-props)
303
+
304
+ ### Default `stringify`
305
+
306
+ When initializing with the `createJhx` function, you can set a default `config.stringify` value to be used for **all calls** to the `jhx` function.
307
+ This can be overridden on a per-call basis.
308
+
309
+ This can be useful when you **primarily use the string output (e.g., HTML templating)** in your application more often than the object output (e.g., JSX templating).
310
+
311
+ ```tsx
312
+ const { jhx, JhxComponent } = createJhx(app, {
313
+ stringify: true, // set default 'stringify' to 'true'
314
+ });
315
+
316
+ const SubmitButton = `
317
+ <button ${jhx({
318
+ post: '/submit',
319
+ swap: 'innerHTML',
320
+ })}>
321
+ Submit
322
+ </button>
323
+ `;
324
+
325
+ const CancelButton = `
326
+ <button ${jhx({
327
+ get: '/cancel',
328
+ swap: 'innerHTML',
329
+ })}>
330
+ Cancel
331
+ </button>
332
+ `;
333
+
334
+ // set 'stringify' to 'false' for object output
335
+ const RefreshButton = (
336
+ <button {...jhx({
337
+ get: '/refresh',
338
+ swap: 'innerHTML',
339
+ }, { stringify: false })}>
340
+ Refresh
341
+ </button>
342
+ );
343
+ ```
344
+
345
+ ---
346
+
347
+ ### Reusing Handlers
348
+
349
+ You can reuse the same handler function for multiple routes.
350
+
351
+ ```ts
352
+ import { JhxHandler } from '@jhxdev/express';
353
+
354
+ const handler: JhxHandler = (_req, reply) => {
355
+ reply.type('application/json').send({ message: 'Response' });
356
+ };
357
+
358
+ jhx({
359
+ get: '/api/1',
360
+ handler,
361
+ });
362
+
363
+ jhx({
364
+ post: '/api/2',
365
+ handler,
366
+ });
367
+
368
+ jhx({
369
+ method: 'get', // generated endpoint
370
+ handler,
371
+ });
372
+ ```
373
+
374
+ If you want to use the same endpoint for different interactions, only one handler function needs to be called.
375
+
376
+ ```ts
377
+ // ensure this is called first to register the route
378
+ jhx({
379
+ get: '/api',
380
+ handler: () => `<div>Response</div>`,
381
+ });
382
+
383
+ jhx({
384
+ get: '/api',
385
+ });
386
+ ```
387
+
388
+ ---
389
+
390
+ ### Multiple Instances
391
+
392
+ Multiple instances of `jhx` and `JhxComponent` can be bound to the same Express instance by **providing a unique `config.prefix` value with every call** to the `createJhx` function.
393
+
394
+ ```ts
395
+ import express from 'express';
396
+ import { createJhx } from '@jhxdev/express';
397
+
398
+ const app = express();
399
+
400
+ // First instance
401
+ const {
402
+ jhx: jhx1,
403
+ JhxComponent: JhxComponent1,
404
+ } = createJhx(app, { prefix: '/api-one' });
405
+
406
+ // Second instance
407
+ const {
408
+ jhx: jhx2,
409
+ JhxComponent: JhxComponent2,
410
+ } = createJhx(app); // 'config.prefix' defaults to '/_jhx'
411
+
412
+ // Second instance
413
+ const {
414
+ jhx: jhx3,
415
+ JhxComponent: JhxComponent3,
416
+ } = createJhx(app, { prefix: '/api-three' });
417
+
418
+
419
+ ```
420
+
421
+ ---
422
+
423
+ ### Custom `render` Handler
424
+
425
+ The `render` handler processes the return values of **all handlers**, unless it is set to `false`, then the handler return values will be sent directly.
426
+
427
+ ```tsx
428
+ import { isValidElement } from "react";
429
+ import { renderToString } from "react-dom/server";
430
+
431
+ createJhx(app, {
432
+ render: async (payload, req, reply) => {
433
+ if (isValidElement(payload)) {
434
+ return renderToString(payload);
435
+ }
436
+ if (payload instanceof Blob) {
437
+ reply.header('Content-Type', 'application/octet-stream');
438
+ return Buffer.from(await payload.arrayBuffer());
439
+ }
440
+ return payload;
441
+ },
442
+ });
443
+ ```
444
+
445
+ ---
446
+
447
+ ### Custom `middleware` Handler(s)
448
+
449
+ You can define one or more middleware handlers to run before the route handlers created by a particular `jhx` function.
450
+
451
+ When a middleware handler returns a value other than `void`/`undefined`, the value will be sent directly and the route handler will not be executed.
452
+
453
+ ```ts
454
+ const { jhx, JhxComponent } = createJhx(app, {
455
+ prefix: '/api',
456
+ middleware: (req, reply) => {
457
+ console.log(`Request made to: ${req.url}`);
458
+ },
459
+ });
460
+
461
+ const { jhx: authJhx, JhxComponent: AuthJhxComponent } = createJhx(app, {
462
+ prefix: '/auth-api',
463
+ middleware: [
464
+ (req) => {
465
+ console.log(`Auth route request made to: ${req.url}`);
466
+ },
467
+ async (req, reply) => {
468
+ const authorized = await checkAuth(req);
469
+ if (!authorized) {
470
+ reply.status(401);
471
+ return `<div>Unauthorized</div>`;
472
+ }
473
+ },
474
+ ],
475
+ });
476
+ ```
477
+
478
+ ---
479
+
480
+ ### Predefined `routes`
481
+
482
+ Since the `jhx` function registers routes at runtime, **some routes will not exist until their corresponding `jhx` function is called**.
483
+
484
+ To ensure routes are available beforehand, define them by doing at least one of the following:
485
+ 1. Define the route(s) in the `config.routes` option when calling the `createJhx` function.
486
+ 2. Call the `jhx` function before starting the server.
487
+ 3. Use the `addRoute` or `addRoutes` utility functions on the `jhx` instance.
488
+
489
+ ```tsx
490
+ const app = express();
491
+
492
+ // 1.
493
+ const { jhx } = createJhx(app, {
494
+ routes: [
495
+ {
496
+ route: '/latest', // defaults to 'GET' method
497
+ handler: async () => {
498
+ return `<div>${await db.getData()}</div>`;
499
+ },
500
+ },
501
+ {
502
+ route: '/submit',
503
+ method: 'POST',
504
+ handler: (req) => {
505
+ return (
506
+ <div>
507
+ Submitted Data: {JSON.stringify(req.body)}
508
+ </div>
509
+ );
510
+ },
511
+ },
512
+ ],
513
+ });
514
+
515
+ // 2.
516
+ jhx({
517
+ get: '/static',
518
+ handler: async () => {
519
+ return `<div>Static Route</div>`;
520
+ },
521
+ })
522
+
523
+ // 3.
524
+ jhx.addRoute({
525
+ route: '/info',
526
+ method: 'GET',
527
+ handler: () => `<div>Info Route</div>`,
528
+ });
529
+
530
+ app.listen(3000, () => {/* ... */});
531
+ ```
532
+
533
+ ---
534
+
535
+ ### DOM Interactions & Type Safety
536
+
537
+ In all event handlers and DOM-related props, you have access to the `document`, `window`, and `htmx` objects in the DOM.
538
+ The `TDom` generic allows you to **define additional variables** that are available in the DOM.
539
+
540
+ > See the [`jhx` repository](https://github.com/nick-hio/jhx/tree/main/packages/jhx#dom-interactions--type-safety) for more details about the `TDom` generic.
541
+
542
+ When using the `createJhx` function, you can specify a default `TDom` type which will be used for **all event handlers and DOM-related props** when using `jhx` and `JhxComponent`.
543
+ This can be overridden on a per-call basis.
544
+
545
+ ```tsx
546
+ type BaseDom = { darkMode?: boolean };
547
+
548
+ // the variables defined in `BaseDom` will be is available for `jhx` and `JhxComponent`
549
+ const { jhx, JhxComponent } = createJhx<BaseDom>(app);
550
+
551
+ jhx({
552
+ vals: ({ darkMode }) => ({
553
+ darkMode: darkMode ?? false,
554
+ }),
555
+ });
556
+ jhx({
557
+ headers: ({ darkMode }) => ({
558
+ 'X-Color-Scheme': darkMode ? 'dark' : 'light',
559
+ }),
560
+ });
561
+
562
+ type SearchPageDom = { searchQuery: string };
563
+
564
+ // overrides the default `BaseDom` type
565
+ jhx<SearchPageDom>({
566
+ vals: ({ searchQuery }) => ({
567
+ query: searchQuery,
568
+ }),
569
+ });
570
+ ```
571
+