@formbox/htmx 0.4.0 → 0.4.1

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,59 @@ 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
+ ```ts
101
+ import {
102
+ compileTemplates,
103
+ loadDefaultTemplates,
104
+ loadTemplates,
105
+ } from "@formbox/htmx";
106
+
107
+ const templates = {
108
+ ...(await loadDefaultTemplates()),
109
+ ...(await loadTemplates("./questionnaire-templates")),
110
+ ...compileTemplates({
111
+ Form: `
112
+ <form{{{attrs attributes}}} hx-target="#questionnaire-app">
113
+ {{{fields}}}
114
+ </form>
115
+ `,
116
+ }),
117
+ };
118
+
119
+ async function handler(request: Request): Promise<Response> {
120
+ const rendered = await renderQuestionnaire(request);
121
+ const body =
122
+ request.headers.get("hx-request") === "true"
123
+ ? questionnaireApp(rendered)
124
+ : layout(questionnaireApp(rendered));
125
+
126
+ return html(body);
127
+ }
128
+
129
+ function questionnaireApp(rendered: {
130
+ form: string;
131
+ response: unknown;
132
+ }): string {
133
+ return `
134
+ <div id="questionnaire-app">
135
+ ${rendered.form}
136
+ <pre>${JSON.stringify(rendered.response, null, 2)}</pre>
137
+ </div>
138
+ `;
139
+ }
140
+ ```
141
+
142
+ Use the default form swap when the form is the only dynamic region. Use an
143
+ application wrapper when the result of `renderer.process(formData)` affects
144
+ nearby UI outside the form.
145
+
93
146
  ## Lifecycle
94
147
 
95
148
  Create one renderer instance for one request/render cycle:
@@ -129,8 +182,8 @@ const renderer = new QuestionnaireRenderer({
129
182
 
130
183
  `questionnaireResponse` is optional initial state.
131
184
  `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.
185
+ `templates` is required; call `await loadDefaultTemplates()` for the package
186
+ defaults, or merge those templates with application overrides.
134
187
 
135
188
  ### `renderer.process(formData)`
136
189
 
@@ -182,10 +235,10 @@ Use a custom `Form` template when the application needs to add shell markup or
182
235
  adjust attributes:
183
236
 
184
237
  ```ts
185
- import { compileTemplates, loadNativeTemplates } from "@formbox/htmx";
238
+ import { compileTemplates, loadDefaultTemplates } from "@formbox/htmx";
186
239
 
187
240
  const templates = {
188
- ...(await loadNativeTemplates()),
241
+ ...(await loadDefaultTemplates()),
189
242
  ...compileTemplates({
190
243
  Form: `
191
244
  <form{{{attrs attributes}}}>
@@ -245,22 +298,22 @@ const templates = compileTemplates({
245
298
  });
246
299
  ```
247
300
 
248
- Load the native templates explicitly:
301
+ Load the default templates explicitly:
249
302
 
250
303
  ```ts
251
- import { loadNativeTemplates } from "@formbox/htmx";
304
+ import { loadDefaultTemplates } from "@formbox/htmx";
252
305
 
253
- const templates = await loadNativeTemplates();
306
+ const templates = await loadDefaultTemplates();
254
307
  ```
255
308
 
256
309
  If you prefer overrides as files, load a directory of `*.html.hbs` files and
257
- merge the result with the native templates:
310
+ merge the result with the default templates:
258
311
 
259
312
  ```ts
260
- import { loadNativeTemplates, loadTemplates } from "@formbox/htmx";
313
+ import { loadDefaultTemplates, loadTemplates } from "@formbox/htmx";
261
314
 
262
315
  const templates = {
263
- ...(await loadNativeTemplates()),
316
+ ...(await loadDefaultTemplates()),
264
317
  ...(await loadTemplates("./questionnaire-templates")),
265
318
  };
266
319
  ```
@@ -285,7 +338,7 @@ Available Handlebars helpers:
285
338
  Use triple braces for renderer-provided HTML slots such as `fields`, `children`,
286
339
  `label`, `errors`, and `customOptionForm`.
287
340
 
288
- Native templates and user templates use the same data shape. The package does
341
+ Default templates and user templates use the same data shape. The package does
289
342
  not keep a separate JSX fallback path.
290
343
 
291
344
  ### `renderer.getQuestionnaireResponse()`
package/dist/index.d.ts CHANGED
@@ -298,7 +298,9 @@ 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
+
303
+ export declare const loadNativeTemplates: typeof loadDefaultTemplates;
302
304
 
303
305
  export declare function loadTemplates(directory: string | URL): Promise<Templates>;
304
306
 
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,10 +59791,11 @@ 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
  }
59798
+ const loadNativeTemplates = loadDefaultTemplates;
59798
59799
  async function loadTemplates(directory) {
59799
59800
  const sources = {};
59800
59801
  const entries = await readdir(directory, { withFileTypes: true });
@@ -62382,6 +62383,7 @@ export {
62382
62383
  compileTemplate,
62383
62384
  compileTemplates,
62384
62385
  htmlAttributes,
62386
+ loadDefaultTemplates,
62385
62387
  loadNativeTemplates,
62386
62388
  loadTemplates
62387
62389
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formbox/htmx",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Server-rendered HTMX HTML renderer for Formbox FHIR Questionnaires",
5
5
  "private": false,
6
6
  "type": "module",