@formbox/htmx 0.4.0 → 0.4.2

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/README.md CHANGED
@@ -9,10 +9,10 @@ React, hydrate React, or manage MobX.
9
9
  The main API is built around a short-lived renderer instance:
10
10
 
11
11
  ```ts
12
- import { QuestionnaireRenderer, loadNativeTemplates } from "@formbox/htmx";
12
+ import { QuestionnaireRenderer, loadDefaultTemplates } from "@formbox/htmx";
13
13
 
14
14
  const route = "/questionnaire";
15
- const templates = await loadNativeTemplates();
15
+ const templates = await loadDefaultTemplates();
16
16
  const renderer = new QuestionnaireRenderer({
17
17
  token: "encounter-questionnaire",
18
18
  templates,
@@ -55,9 +55,9 @@ field encoding and parses the submitted payload in `renderer.process()`.
55
55
  ## Basic Integration
56
56
 
57
57
  ```ts
58
- import { QuestionnaireRenderer, loadNativeTemplates } from "@formbox/htmx";
58
+ import { QuestionnaireRenderer, loadDefaultTemplates } from "@formbox/htmx";
59
59
 
60
- const templates = await loadNativeTemplates();
60
+ const templates = await loadDefaultTemplates();
61
61
 
62
62
  async function renderQuestionnaire(request: Request): Promise<Response> {
63
63
  const route = "/questionnaire";
@@ -90,6 +90,72 @@ async function renderQuestionnaire(request: Request): Promise<Response> {
90
90
  }
91
91
  ```
92
92
 
93
+ ## HTMX Integration
94
+
95
+ The renderer does not own your page shell. If a POST should update more than
96
+ the form itself, such as a status label or a rendered `QuestionnaireResponse`
97
+ preview beside the form, target an application-owned wrapper and return that
98
+ same wrapper for HTMX requests.
99
+
100
+ For dynamic questionnaires, prefer morphdom swaps so focus and nearby DOM state
101
+ survive server-rendered updates better than plain `outerHTML` replacement:
102
+
103
+ ```ts
104
+ import {
105
+ compileTemplates,
106
+ loadDefaultTemplates,
107
+ loadTemplates,
108
+ } from "@formbox/htmx";
109
+
110
+ const templates = {
111
+ ...(await loadDefaultTemplates()),
112
+ ...(await loadTemplates("./questionnaire-templates")),
113
+ ...compileTemplates({
114
+ Form: `
115
+ <form{{{attrs attributes}}} hx-target="#questionnaire-app" hx-swap="morphdom">
116
+ {{{fields}}}
117
+ </form>
118
+ `,
119
+ }),
120
+ };
121
+
122
+ async function handler(request: Request): Promise<Response> {
123
+ const rendered = await renderQuestionnaire(request);
124
+ const body =
125
+ request.headers.get("hx-request") === "true"
126
+ ? questionnaireApp(rendered)
127
+ : layout(questionnaireApp(rendered));
128
+
129
+ return html(body);
130
+ }
131
+
132
+ function questionnaireApp(rendered: {
133
+ form: string;
134
+ response: unknown;
135
+ }): string {
136
+ return `
137
+ <div id="questionnaire-app">
138
+ ${rendered.form}
139
+ <pre>${JSON.stringify(rendered.response, null, 2)}</pre>
140
+ </div>
141
+ `;
142
+ }
143
+ ```
144
+
145
+ Include the HTMX morphdom extension in the application shell:
146
+
147
+ ```html
148
+ <script src="https://unpkg.com/morphdom@2.7.8/dist/morphdom-umd.min.js"></script>
149
+ <script src="https://unpkg.com/htmx-ext-morphdom-swap@2.0.0/morphdom-swap.js"></script>
150
+ <body hx-ext="morphdom-swap">
151
+ <div id="questionnaire-app">...</div>
152
+ </body>
153
+ ```
154
+
155
+ Use the default form swap when the form is the only dynamic region. Use an
156
+ application wrapper when the result of `renderer.process(formData)` affects
157
+ nearby UI outside the form.
158
+
93
159
  ## Lifecycle
94
160
 
95
161
  Create one renderer instance for one request/render cycle:
@@ -129,8 +195,8 @@ const renderer = new QuestionnaireRenderer({
129
195
 
130
196
  `questionnaireResponse` is optional initial state.
131
197
  `token` is required and must be unique for each rendered form on the same page.
132
- `templates` is required; call `await loadNativeTemplates()` for the built-in
133
- file templates, or merge those templates with application overrides.
198
+ `templates` is required; call `await loadDefaultTemplates()` for the package
199
+ defaults, or merge those templates with application overrides.
134
200
 
135
201
  ### `renderer.process(formData)`
136
202
 
@@ -182,10 +248,10 @@ Use a custom `Form` template when the application needs to add shell markup or
182
248
  adjust attributes:
183
249
 
184
250
  ```ts
185
- import { compileTemplates, loadNativeTemplates } from "@formbox/htmx";
251
+ import { compileTemplates, loadDefaultTemplates } from "@formbox/htmx";
186
252
 
187
253
  const templates = {
188
- ...(await loadNativeTemplates()),
254
+ ...(await loadDefaultTemplates()),
189
255
  ...compileTemplates({
190
256
  Form: `
191
257
  <form{{{attrs attributes}}}>
@@ -245,22 +311,22 @@ const templates = compileTemplates({
245
311
  });
246
312
  ```
247
313
 
248
- Load the native templates explicitly:
314
+ Load the default templates explicitly:
249
315
 
250
316
  ```ts
251
- import { loadNativeTemplates } from "@formbox/htmx";
317
+ import { loadDefaultTemplates } from "@formbox/htmx";
252
318
 
253
- const templates = await loadNativeTemplates();
319
+ const templates = await loadDefaultTemplates();
254
320
  ```
255
321
 
256
322
  If you prefer overrides as files, load a directory of `*.html.hbs` files and
257
- merge the result with the native templates:
323
+ merge the result with the default templates:
258
324
 
259
325
  ```ts
260
- import { loadNativeTemplates, loadTemplates } from "@formbox/htmx";
326
+ import { loadDefaultTemplates, loadTemplates } from "@formbox/htmx";
261
327
 
262
328
  const templates = {
263
- ...(await loadNativeTemplates()),
329
+ ...(await loadDefaultTemplates()),
264
330
  ...(await loadTemplates("./questionnaire-templates")),
265
331
  };
266
332
  ```
@@ -285,7 +351,7 @@ Available Handlebars helpers:
285
351
  Use triple braces for renderer-provided HTML slots such as `fields`, `children`,
286
352
  `label`, `errors`, and `customOptionForm`.
287
353
 
288
- Native templates and user templates use the same data shape. The package does
354
+ Default templates and user templates use the same data shape. The package does
289
355
  not keep a separate JSX fallback path.
290
356
 
291
357
  ### `renderer.getQuestionnaireResponse()`
package/dist/index.d.ts CHANGED
@@ -298,7 +298,7 @@ export declare type LinkTemplateProperties = Omit<TemplateBase<LinkProperties>,
298
298
  readonly children: string;
299
299
  };
300
300
 
301
- export declare function loadNativeTemplates(): Promise<RequiredTemplates>;
301
+ export declare function loadDefaultTemplates(): Promise<RequiredTemplates>;
302
302
 
303
303
  export declare function loadTemplates(directory: string | URL): Promise<Templates>;
304
304
 
package/dist/index.js CHANGED
@@ -59781,7 +59781,7 @@ function compileTemplates(sources) {
59781
59781
  })
59782
59782
  );
59783
59783
  }
59784
- async function loadNativeTemplates() {
59784
+ async function loadDefaultTemplates() {
59785
59785
  const templates = await loadTemplates(
59786
59786
  new URL(
59787
59787
  /* @vite-ignore */
@@ -59791,7 +59791,7 @@ async function loadNativeTemplates() {
59791
59791
  );
59792
59792
  const missing = templateNames.filter((name) => templates[name] === void 0);
59793
59793
  if (missing.length > 0) {
59794
- throw new Error(`Missing native template files: ${missing.join(", ")}`);
59794
+ throw new Error(`Missing default template files: ${missing.join(", ")}`);
59795
59795
  }
59796
59796
  return templates;
59797
59797
  }
@@ -62382,6 +62382,6 @@ export {
62382
62382
  compileTemplate,
62383
62383
  compileTemplates,
62384
62384
  htmlAttributes,
62385
- loadNativeTemplates,
62385
+ loadDefaultTemplates,
62386
62386
  loadTemplates
62387
62387
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formbox/htmx",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Server-rendered HTMX HTML renderer for Formbox FHIR Questionnaires",
5
5
  "private": false,
6
6
  "type": "module",