@formbox/htmx 0.5.0 → 0.7.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/README.md +43 -7
- package/dist/index.d.ts +71 -7
- package/dist/index.js +103 -65
- package/dist/templates/AnswerList.html.hbs +3 -0
- package/dist/templates/AnswerScaffold.html.hbs +3 -0
- package/dist/templates/Checkbox.html.hbs +3 -0
- package/dist/templates/CheckboxList.html.hbs +3 -0
- package/dist/templates/CustomOptionForm.html.hbs +3 -0
- package/dist/templates/DateInput.html.hbs +3 -0
- package/dist/templates/DateTimeInput.html.hbs +3 -0
- package/dist/templates/DisplayRenderer.html.hbs +3 -0
- package/dist/templates/Errors.html.hbs +3 -0
- package/dist/templates/FileInput.html.hbs +3 -0
- package/dist/templates/Flyover.html.hbs +3 -0
- package/dist/templates/Footer.html.hbs +3 -0
- package/dist/templates/Form.html.hbs +21 -4
- package/dist/templates/FormDescription.html.hbs +10 -0
- package/dist/templates/FormTitle.html.hbs +10 -0
- package/dist/templates/GroupList.html.hbs +3 -0
- package/dist/templates/GroupScaffold.html.hbs +3 -0
- package/dist/templates/Header.html.hbs +3 -0
- package/dist/templates/Help.html.hbs +3 -0
- package/dist/templates/InputGroup.html.hbs +3 -0
- package/dist/templates/Label.html.hbs +3 -0
- package/dist/templates/LabelContent.html.hbs +15 -0
- package/dist/templates/LanguageSelector.html.hbs +3 -0
- package/dist/templates/Legal.html.hbs +3 -0
- package/dist/templates/Link.html.hbs +3 -0
- package/dist/templates/Media.html.hbs +29 -0
- package/dist/templates/MultiSelectInput.html.hbs +3 -0
- package/dist/templates/NumberInput.html.hbs +3 -0
- package/dist/templates/OptionDisplay.html.hbs +3 -0
- package/dist/templates/OptionsLoading.html.hbs +3 -0
- package/dist/templates/Pagination.html.hbs +24 -0
- package/dist/templates/QuestionScaffold.html.hbs +3 -0
- package/dist/templates/RadioButton.html.hbs +3 -0
- package/dist/templates/RadioButtonList.html.hbs +3 -0
- package/dist/templates/SelectInput.html.hbs +3 -0
- package/dist/templates/ShortTextStyle.html.hbs +10 -0
- package/dist/templates/SignatureInput.html.hbs +3 -0
- package/dist/templates/SliderInput.html.hbs +3 -0
- package/dist/templates/SpinnerInput.html.hbs +3 -0
- package/dist/templates/Stack.html.hbs +3 -0
- package/dist/templates/SubmitButton.html.hbs +13 -0
- package/dist/templates/TabContainer.html.hbs +3 -0
- package/dist/templates/Table.html.hbs +3 -0
- package/dist/templates/TextArea.html.hbs +3 -0
- package/dist/templates/TextInput.html.hbs +3 -0
- package/dist/templates/TimeInput.html.hbs +3 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -113,7 +113,18 @@ const templates = {
|
|
|
113
113
|
...compileTemplates({
|
|
114
114
|
Form: `
|
|
115
115
|
<form{{{attrs attributes}}} hx-target="#questionnaire-app" hx-swap="morphdom">
|
|
116
|
-
{{{
|
|
116
|
+
{{{hiddenFields}}}
|
|
117
|
+
{{{shortTextStyle}}}
|
|
118
|
+
{{{titleHtml}}}
|
|
119
|
+
{{{descriptionHtml}}}
|
|
120
|
+
{{{languageSelector}}}
|
|
121
|
+
{{{errors}}}
|
|
122
|
+
{{{before}}}
|
|
123
|
+
{{{children}}}
|
|
124
|
+
{{{after}}}
|
|
125
|
+
{{{signature}}}
|
|
126
|
+
{{{paginationHtml}}}
|
|
127
|
+
{{{submitButton}}}
|
|
117
128
|
</form>
|
|
118
129
|
`,
|
|
119
130
|
}),
|
|
@@ -162,7 +173,7 @@ Create one renderer instance for one request/render cycle:
|
|
|
162
173
|
|
|
163
174
|
1. `new QuestionnaireRenderer(options)` creates a request-local renderer.
|
|
164
175
|
2. `await renderer.process(formData)` applies submitted form state and returns submit result.
|
|
165
|
-
3. `await renderer.render()` returns HTML
|
|
176
|
+
3. `await renderer.render()` returns form HTML for the current renderer state.
|
|
166
177
|
4. `renderer.getQuestionnaireResponse()` reads the current FHIR response.
|
|
167
178
|
5. `renderer.dispose()` releases the underlying renderer store.
|
|
168
179
|
|
|
@@ -256,7 +267,18 @@ const templates = {
|
|
|
256
267
|
Form: `
|
|
257
268
|
<form{{{attrs attributes}}}>
|
|
258
269
|
${csrf}
|
|
259
|
-
{{{
|
|
270
|
+
{{{hiddenFields}}}
|
|
271
|
+
{{{shortTextStyle}}}
|
|
272
|
+
{{{titleHtml}}}
|
|
273
|
+
{{{descriptionHtml}}}
|
|
274
|
+
{{{languageSelector}}}
|
|
275
|
+
{{{errors}}}
|
|
276
|
+
{{{before}}}
|
|
277
|
+
{{{children}}}
|
|
278
|
+
{{{after}}}
|
|
279
|
+
{{{signature}}}
|
|
280
|
+
{{{paginationHtml}}}
|
|
281
|
+
{{{submitButton}}}
|
|
260
282
|
</form>
|
|
261
283
|
`,
|
|
262
284
|
}),
|
|
@@ -305,8 +327,21 @@ Callbacks and Handlebars strings can be mixed:
|
|
|
305
327
|
```ts
|
|
306
328
|
const templates = compileTemplates({
|
|
307
329
|
TextInput: `<input{{{fieldAttributes}}}{{{attr "id" id}}}>`,
|
|
308
|
-
Form(
|
|
309
|
-
return `<form${htmlAttributes(attributes)}>${
|
|
330
|
+
Form(properties) {
|
|
331
|
+
return `<form${htmlAttributes(properties.attributes)}>${[
|
|
332
|
+
properties.hiddenFields,
|
|
333
|
+
properties.shortTextStyle,
|
|
334
|
+
properties.titleHtml ?? "",
|
|
335
|
+
properties.descriptionHtml ?? "",
|
|
336
|
+
properties.languageSelector ?? "",
|
|
337
|
+
properties.errors ?? "",
|
|
338
|
+
properties.before ?? "",
|
|
339
|
+
properties.children,
|
|
340
|
+
properties.after ?? "",
|
|
341
|
+
properties.signature ?? "",
|
|
342
|
+
properties.paginationHtml ?? "",
|
|
343
|
+
properties.submitButton,
|
|
344
|
+
].join("")}</form>`;
|
|
310
345
|
},
|
|
311
346
|
});
|
|
312
347
|
```
|
|
@@ -348,8 +383,9 @@ Available Handlebars helpers:
|
|
|
348
383
|
- `{{{attrs attributes}}}` renders an object of escaped HTML attributes.
|
|
349
384
|
- `{{{fieldAttributes}}}` renders `data-fb-link-id`, `data-fb-field`, `name`, and `hx-include` for the current field.
|
|
350
385
|
|
|
351
|
-
Use triple braces for renderer-provided HTML slots such as `
|
|
352
|
-
`label`, `errors`, and
|
|
386
|
+
Use triple braces for renderer-provided HTML slots such as `hiddenFields`,
|
|
387
|
+
`children`, `paginationHtml`, `submitButton`, `label`, `errors`, and
|
|
388
|
+
`customOptionForm`.
|
|
353
389
|
|
|
354
390
|
Default templates and user templates use the same data shape. The package does
|
|
355
391
|
not keep a separate JSX fallback path.
|
package/dist/index.d.ts
CHANGED
|
@@ -285,9 +285,9 @@ export declare type FooterTemplateProperties = Omit<TemplateBase<FooterPropertie
|
|
|
285
285
|
readonly children: string;
|
|
286
286
|
};
|
|
287
287
|
|
|
288
|
-
declare type
|
|
289
|
-
|
|
290
|
-
|
|
288
|
+
export declare type FormDescriptionTemplateProperties = {
|
|
289
|
+
readonly description: string;
|
|
290
|
+
};
|
|
291
291
|
|
|
292
292
|
declare type FormPagination = {
|
|
293
293
|
current: number;
|
|
@@ -319,12 +319,21 @@ export declare type FormTemplateProperties = Omit<TemplateBase<FormProperties>,
|
|
|
319
319
|
readonly before?: string | undefined;
|
|
320
320
|
readonly children: string;
|
|
321
321
|
readonly errors?: string | undefined;
|
|
322
|
-
readonly
|
|
322
|
+
readonly hiddenFields: string;
|
|
323
323
|
readonly attributes: HtmlAttributes;
|
|
324
|
+
readonly titleHtml?: string | undefined;
|
|
325
|
+
readonly descriptionHtml?: string | undefined;
|
|
324
326
|
readonly languageSelector?: string | undefined;
|
|
325
327
|
readonly pagination?: TemplateFormPagination | undefined;
|
|
328
|
+
readonly paginationHtml?: string | undefined;
|
|
329
|
+
readonly shortTextStyle: string;
|
|
326
330
|
readonly signature?: string | undefined;
|
|
327
331
|
readonly submitLabel: string;
|
|
332
|
+
readonly submitButton: string;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
export declare type FormTitleTemplateProperties = {
|
|
336
|
+
readonly title: string;
|
|
328
337
|
};
|
|
329
338
|
|
|
330
339
|
declare type GroupListProperties = {
|
|
@@ -432,6 +441,17 @@ export declare function isPreservedOptionToken(token: string): boolean;
|
|
|
432
441
|
|
|
433
442
|
declare type LabelAs = "legend" | "label" | "text";
|
|
434
443
|
|
|
444
|
+
export declare type LabelContentTemplateProperties = {
|
|
445
|
+
readonly children: string;
|
|
446
|
+
readonly prefix?: string | undefined;
|
|
447
|
+
readonly shortText?: string | undefined;
|
|
448
|
+
readonly required?: boolean | undefined;
|
|
449
|
+
readonly help?: string | undefined;
|
|
450
|
+
readonly legal?: string | undefined;
|
|
451
|
+
readonly flyover?: string | undefined;
|
|
452
|
+
readonly hasShortText: boolean;
|
|
453
|
+
};
|
|
454
|
+
|
|
435
455
|
declare type LabelProperties = {
|
|
436
456
|
prefix?: ReactNode;
|
|
437
457
|
shortText?: string | undefined;
|
|
@@ -519,7 +539,23 @@ export declare function loadDefaultTemplates(): Promise<RequiredTemplates>;
|
|
|
519
539
|
|
|
520
540
|
export declare function loadTemplates(directory: string | URL): Promise<Templates>;
|
|
521
541
|
|
|
522
|
-
export declare function mediaHtml(attachment: Attachment | undefined, fallbackLabel: string, id?: string | undefined): string;
|
|
542
|
+
export declare function mediaHtml(templates: Pick<RequiredTemplates, "Media">, attachment: Attachment | undefined, fallbackLabel: string, id?: string | undefined): string;
|
|
543
|
+
|
|
544
|
+
export declare type MediaKind = "fallback" | "image" | "audio" | "video" | "link";
|
|
545
|
+
|
|
546
|
+
export declare type MediaTemplateProperties = {
|
|
547
|
+
readonly attachment: Attachment;
|
|
548
|
+
readonly id?: string | undefined;
|
|
549
|
+
readonly label: string;
|
|
550
|
+
readonly source?: string | undefined;
|
|
551
|
+
readonly contentType?: string | undefined;
|
|
552
|
+
readonly kind: MediaKind;
|
|
553
|
+
readonly isFallback: boolean;
|
|
554
|
+
readonly isImage: boolean;
|
|
555
|
+
readonly isAudio: boolean;
|
|
556
|
+
readonly isVideo: boolean;
|
|
557
|
+
readonly isLink: boolean;
|
|
558
|
+
};
|
|
523
559
|
|
|
524
560
|
declare type MultiSelectInputProperties = {
|
|
525
561
|
options: readonly OptionItem[];
|
|
@@ -619,6 +655,18 @@ export declare function optionValueName(path: NodePath, token: string): string;
|
|
|
619
655
|
|
|
620
656
|
export declare const PAGE_FIELD = "fb[page]";
|
|
621
657
|
|
|
658
|
+
export declare function pageHiddenField(currentPage: number | undefined): string;
|
|
659
|
+
|
|
660
|
+
export declare type PaginationTemplateProperties = TemplateFormPagination & {
|
|
661
|
+
readonly actionName: string;
|
|
662
|
+
readonly previousAction: "page-prev";
|
|
663
|
+
readonly nextAction: "page-next";
|
|
664
|
+
readonly navigationLabel: string;
|
|
665
|
+
readonly currentLabel: string;
|
|
666
|
+
readonly previousTargetLabel: string;
|
|
667
|
+
readonly nextTargetLabel: string;
|
|
668
|
+
};
|
|
669
|
+
|
|
622
670
|
export declare function pathControlId(token: string, path: NodePath | undefined, ...parts: Array<string | number | undefined>): string | undefined;
|
|
623
671
|
|
|
624
672
|
declare type PlaceholderString<Key extends string> = `${string}{${Key}}${string}`;
|
|
@@ -800,6 +848,8 @@ export declare type SelectOptionTemplateItem = TemplateOptionItem & {
|
|
|
800
848
|
readonly selected: boolean;
|
|
801
849
|
};
|
|
802
850
|
|
|
851
|
+
export declare type ShortTextStyleTemplateProperties = Record<string, never>;
|
|
852
|
+
|
|
803
853
|
declare type SignatureInputProperties = {
|
|
804
854
|
value: string | undefined;
|
|
805
855
|
id: string;
|
|
@@ -1001,6 +1051,13 @@ declare type Strings = {
|
|
|
1001
1051
|
|
|
1002
1052
|
export declare const SUBMIT_ATTEMPTED_FIELD = "fb[submitAttempted]";
|
|
1003
1053
|
|
|
1054
|
+
export declare type SubmitButtonTemplateProperties = {
|
|
1055
|
+
readonly id?: string | undefined;
|
|
1056
|
+
readonly actionName: string;
|
|
1057
|
+
readonly value: "submit";
|
|
1058
|
+
readonly label: string;
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1004
1061
|
declare type TabContainerProperties = {
|
|
1005
1062
|
path?: NodePath | undefined;
|
|
1006
1063
|
header?: ReactNode;
|
|
@@ -1090,13 +1147,13 @@ export declare type TemplateFormPagination = Omit<FormPagination, "onNext" | "on
|
|
|
1090
1147
|
|
|
1091
1148
|
export declare type TemplateName = keyof Templates;
|
|
1092
1149
|
|
|
1093
|
-
export declare const templateNames: readonly ["TextInput", "TextArea", "NumberInput", "DateInput", "DateTimeInput", "TimeInput", "SliderInput", "SpinnerInput", "OptionDisplay", "SelectInput", "RadioButton", "RadioButtonList", "Checkbox", "CheckboxList", "MultiSelectInput", "CustomOptionForm", "Errors", "Label", "QuestionScaffold", "OptionsLoading", "Help", "Legal", "Flyover", "Header", "Footer", "Form", "Stack", "AnswerList", "AnswerScaffold", "GroupList", "GroupScaffold", "Table", "InputGroup", "FileInput", "SignatureInput", "DisplayRenderer", "TabContainer", "Link", "LanguageSelector"];
|
|
1150
|
+
export declare const templateNames: readonly ["TextInput", "TextArea", "NumberInput", "DateInput", "DateTimeInput", "TimeInput", "SliderInput", "SpinnerInput", "OptionDisplay", "SelectInput", "RadioButton", "RadioButtonList", "Checkbox", "CheckboxList", "MultiSelectInput", "CustomOptionForm", "Media", "Errors", "Label", "LabelContent", "QuestionScaffold", "OptionsLoading", "Help", "Legal", "Flyover", "Header", "Footer", "FormTitle", "FormDescription", "Pagination", "SubmitButton", "ShortTextStyle", "Form", "Stack", "AnswerList", "AnswerScaffold", "GroupList", "GroupScaffold", "Table", "InputGroup", "FileInput", "SignatureInput", "DisplayRenderer", "TabContainer", "Link", "LanguageSelector"];
|
|
1094
1151
|
|
|
1095
1152
|
export declare type TemplateOptionItem = Omit<OptionItem, "label"> & {
|
|
1096
1153
|
readonly label: string;
|
|
1097
1154
|
};
|
|
1098
1155
|
|
|
1099
|
-
export declare type TemplateProperties = TextInputTemplateProperties | TextAreaTemplateProperties | NumberInputTemplateProperties | DateInputTemplateProperties | DateTimeInputTemplateProperties | TimeInputTemplateProperties | SliderInputTemplateProperties | SpinnerInputTemplateProperties | OptionDisplayTemplateProperties | SelectInputTemplateProperties | RadioButtonTemplateProperties | RadioButtonListTemplateProperties | CheckboxTemplateProperties | CheckboxListTemplateProperties | MultiSelectInputTemplateProperties | CustomOptionFormTemplateProperties | ErrorsTemplateProperties | LabelTemplateProperties | QuestionScaffoldTemplateProperties | OptionsLoadingTemplateProperties | HelpTemplateProperties | LegalTemplateProperties | FlyoverTemplateProperties | HeaderTemplateProperties | FooterTemplateProperties | FormTemplateProperties | StackTemplateProperties | AnswerListTemplateProperties | AnswerScaffoldTemplateProperties | GroupListTemplateProperties | GroupScaffoldTemplateProperties | TableTemplateProperties | InputGroupTemplateProperties | FileInputTemplateProperties | SignatureInputTemplateProperties | DisplayRendererTemplateProperties | TabContainerTemplateProperties | LinkTemplateProperties | LanguageSelectorTemplateProperties;
|
|
1156
|
+
export declare type TemplateProperties = TextInputTemplateProperties | TextAreaTemplateProperties | NumberInputTemplateProperties | DateInputTemplateProperties | DateTimeInputTemplateProperties | TimeInputTemplateProperties | SliderInputTemplateProperties | SpinnerInputTemplateProperties | OptionDisplayTemplateProperties | SelectInputTemplateProperties | RadioButtonTemplateProperties | RadioButtonListTemplateProperties | CheckboxTemplateProperties | CheckboxListTemplateProperties | MultiSelectInputTemplateProperties | CustomOptionFormTemplateProperties | MediaTemplateProperties | ErrorsTemplateProperties | LabelTemplateProperties | LabelContentTemplateProperties | QuestionScaffoldTemplateProperties | OptionsLoadingTemplateProperties | HelpTemplateProperties | LegalTemplateProperties | FlyoverTemplateProperties | HeaderTemplateProperties | FooterTemplateProperties | FormTitleTemplateProperties | FormDescriptionTemplateProperties | PaginationTemplateProperties | SubmitButtonTemplateProperties | ShortTextStyleTemplateProperties | FormTemplateProperties | StackTemplateProperties | AnswerListTemplateProperties | AnswerScaffoldTemplateProperties | GroupListTemplateProperties | GroupScaffoldTemplateProperties | TableTemplateProperties | InputGroupTemplateProperties | FileInputTemplateProperties | SignatureInputTemplateProperties | DisplayRendererTemplateProperties | TabContainerTemplateProperties | LinkTemplateProperties | LanguageSelectorTemplateProperties;
|
|
1100
1157
|
|
|
1101
1158
|
export declare interface Templates {
|
|
1102
1159
|
readonly TextInput?: Template<TextInputTemplateProperties> | undefined;
|
|
@@ -1115,8 +1172,10 @@ export declare interface Templates {
|
|
|
1115
1172
|
readonly CheckboxList?: Template<CheckboxListTemplateProperties> | undefined;
|
|
1116
1173
|
readonly MultiSelectInput?: Template<MultiSelectInputTemplateProperties> | undefined;
|
|
1117
1174
|
readonly CustomOptionForm?: Template<CustomOptionFormTemplateProperties> | undefined;
|
|
1175
|
+
readonly Media?: Template<MediaTemplateProperties> | undefined;
|
|
1118
1176
|
readonly Errors?: Template<ErrorsTemplateProperties> | undefined;
|
|
1119
1177
|
readonly Label?: Template<LabelTemplateProperties> | undefined;
|
|
1178
|
+
readonly LabelContent?: Template<LabelContentTemplateProperties> | undefined;
|
|
1120
1179
|
readonly QuestionScaffold?: Template<QuestionScaffoldTemplateProperties> | undefined;
|
|
1121
1180
|
readonly OptionsLoading?: Template<OptionsLoadingTemplateProperties> | undefined;
|
|
1122
1181
|
readonly Help?: Template<HelpTemplateProperties> | undefined;
|
|
@@ -1124,6 +1183,11 @@ export declare interface Templates {
|
|
|
1124
1183
|
readonly Flyover?: Template<FlyoverTemplateProperties> | undefined;
|
|
1125
1184
|
readonly Header?: Template<HeaderTemplateProperties> | undefined;
|
|
1126
1185
|
readonly Footer?: Template<FooterTemplateProperties> | undefined;
|
|
1186
|
+
readonly FormTitle?: Template<FormTitleTemplateProperties> | undefined;
|
|
1187
|
+
readonly FormDescription?: Template<FormDescriptionTemplateProperties> | undefined;
|
|
1188
|
+
readonly Pagination?: Template<PaginationTemplateProperties> | undefined;
|
|
1189
|
+
readonly SubmitButton?: Template<SubmitButtonTemplateProperties> | undefined;
|
|
1190
|
+
readonly ShortTextStyle?: Template<ShortTextStyleTemplateProperties> | undefined;
|
|
1127
1191
|
readonly Form?: Template<FormTemplateProperties> | undefined;
|
|
1128
1192
|
readonly Stack?: Template<StackTemplateProperties> | undefined;
|
|
1129
1193
|
readonly AnswerList?: Template<AnswerListTemplateProperties> | undefined;
|
package/dist/index.js
CHANGED
|
@@ -59564,8 +59564,10 @@ const templateNames = [
|
|
|
59564
59564
|
"CheckboxList",
|
|
59565
59565
|
"MultiSelectInput",
|
|
59566
59566
|
"CustomOptionForm",
|
|
59567
|
+
"Media",
|
|
59567
59568
|
"Errors",
|
|
59568
59569
|
"Label",
|
|
59570
|
+
"LabelContent",
|
|
59569
59571
|
"QuestionScaffold",
|
|
59570
59572
|
"OptionsLoading",
|
|
59571
59573
|
"Help",
|
|
@@ -59573,6 +59575,11 @@ const templateNames = [
|
|
|
59573
59575
|
"Flyover",
|
|
59574
59576
|
"Header",
|
|
59575
59577
|
"Footer",
|
|
59578
|
+
"FormTitle",
|
|
59579
|
+
"FormDescription",
|
|
59580
|
+
"Pagination",
|
|
59581
|
+
"SubmitButton",
|
|
59582
|
+
"ShortTextStyle",
|
|
59576
59583
|
"Form",
|
|
59577
59584
|
"Stack",
|
|
59578
59585
|
"AnswerList",
|
|
@@ -59686,43 +59693,30 @@ function isDefined(value) {
|
|
|
59686
59693
|
function isPreservedOptionToken$1(token) {
|
|
59687
59694
|
return token.includes("__custom__") || token.includes("__legacy__");
|
|
59688
59695
|
}
|
|
59689
|
-
function mediaHtml(attachment, fallbackLabel, id2) {
|
|
59696
|
+
function mediaHtml(templates, attachment, fallbackLabel, id2) {
|
|
59690
59697
|
if (attachment === void 0) {
|
|
59691
59698
|
return "";
|
|
59692
59699
|
}
|
|
59693
59700
|
const label = attachment.title ?? attachment.url ?? fallbackLabel;
|
|
59694
59701
|
const source = attachment.url ?? attachmentSource(attachment);
|
|
59695
59702
|
const contentType = attachment.contentType?.toLowerCase();
|
|
59696
|
-
|
|
59697
|
-
|
|
59698
|
-
|
|
59699
|
-
|
|
59700
|
-
|
|
59701
|
-
|
|
59702
|
-
|
|
59703
|
-
|
|
59704
|
-
|
|
59705
|
-
|
|
59706
|
-
|
|
59707
|
-
|
|
59708
|
-
|
|
59703
|
+
const kind = source === void 0 ? "fallback" : contentType?.startsWith("image/") ? "image" : contentType?.startsWith("audio/") ? "audio" : contentType?.startsWith("video/") ? "video" : "link";
|
|
59704
|
+
return templates.Media({
|
|
59705
|
+
attachment,
|
|
59706
|
+
id: id2,
|
|
59707
|
+
label,
|
|
59708
|
+
source,
|
|
59709
|
+
contentType,
|
|
59710
|
+
kind,
|
|
59711
|
+
isFallback: kind === "fallback",
|
|
59712
|
+
isImage: kind === "image",
|
|
59713
|
+
isAudio: kind === "audio",
|
|
59714
|
+
isVideo: kind === "video",
|
|
59715
|
+
isLink: kind === "link"
|
|
59716
|
+
});
|
|
59709
59717
|
}
|
|
59710
|
-
function
|
|
59711
|
-
|
|
59712
|
-
return [
|
|
59713
|
-
shortTextStyle ?? "",
|
|
59714
|
-
`<input type="hidden" name="${PAGE_FIELD}" value="${String(properties.pagination?.current ?? 1)}">`,
|
|
59715
|
-
properties.title ? `<h1>${escapeHtml$1(properties.title)}</h1>` : "",
|
|
59716
|
-
properties.description ? `<p>${escapeHtml$1(properties.description)}</p>` : "",
|
|
59717
|
-
properties.languageSelector ?? "",
|
|
59718
|
-
properties.errors ?? "",
|
|
59719
|
-
properties.before ?? "",
|
|
59720
|
-
properties.children,
|
|
59721
|
-
properties.after ?? "",
|
|
59722
|
-
properties.signature ?? "",
|
|
59723
|
-
renderPagination(properties),
|
|
59724
|
-
`<button type="submit"${attribute("id", stableId(properties.id, "submit"))} name="${ACTION_FIELD}" value="submit">${escapeHtml$1(properties.submitLabel)}</button>`
|
|
59725
|
-
].join("");
|
|
59718
|
+
function pageHiddenField(currentPage) {
|
|
59719
|
+
return `<input type="hidden" name="${PAGE_FIELD}" value="${String(currentPage ?? 1)}">`;
|
|
59726
59720
|
}
|
|
59727
59721
|
function fieldAttributes$1(path2, field) {
|
|
59728
59722
|
if (field === "signature") {
|
|
@@ -59861,19 +59855,6 @@ function defaultAttributes(action2) {
|
|
|
59861
59855
|
"hx-include": "closest form"
|
|
59862
59856
|
};
|
|
59863
59857
|
}
|
|
59864
|
-
function renderPagination(properties) {
|
|
59865
|
-
const pagination = properties.pagination;
|
|
59866
|
-
if (!pagination) {
|
|
59867
|
-
return "";
|
|
59868
|
-
}
|
|
59869
|
-
return [
|
|
59870
|
-
"<nav>",
|
|
59871
|
-
pagination.disabledPrev ? "" : `<button type="submit"${attribute("id", pagination.previousId)} name="${ACTION_FIELD}" value="page-prev">${escapeHtml$1(pagination.previousLabel)}</button>`,
|
|
59872
|
-
`<span>${String(pagination.current)} / ${String(pagination.total)}</span>`,
|
|
59873
|
-
pagination.disabledNext ? "" : `<button type="submit"${attribute("id", pagination.nextId)} name="${ACTION_FIELD}" value="page-next">${escapeHtml$1(pagination.nextLabel)}</button>`,
|
|
59874
|
-
"</nav>"
|
|
59875
|
-
].join("");
|
|
59876
|
-
}
|
|
59877
59858
|
function tableCell(cell, renderHtml) {
|
|
59878
59859
|
return {
|
|
59879
59860
|
token: cell.token,
|
|
@@ -61560,6 +61541,8 @@ function Form(properties) {
|
|
|
61560
61541
|
const renderHtml = useHtml();
|
|
61561
61542
|
const strings2 = useStrings();
|
|
61562
61543
|
const id2 = properties.id ?? token;
|
|
61544
|
+
const submitLabel = strings2.form.submit;
|
|
61545
|
+
const children = renderHtml(properties.children);
|
|
61563
61546
|
const pagination = properties.pagination ? {
|
|
61564
61547
|
current: properties.pagination.current,
|
|
61565
61548
|
total: properties.pagination.total,
|
|
@@ -61570,27 +61553,68 @@ function Form(properties) {
|
|
|
61570
61553
|
previousId: stableId(id2, "pagination", "previous"),
|
|
61571
61554
|
previousLabel: strings2.pagination.previous
|
|
61572
61555
|
} : void 0;
|
|
61556
|
+
const titleHtml = properties.title ? templates.FormTitle({ title: properties.title }) : void 0;
|
|
61557
|
+
const descriptionHtml = properties.description ? templates.FormDescription({
|
|
61558
|
+
description: properties.description
|
|
61559
|
+
}) : void 0;
|
|
61560
|
+
const paginationHtml = pagination ? templates.Pagination({
|
|
61561
|
+
...pagination,
|
|
61562
|
+
actionName: ACTION_FIELD,
|
|
61563
|
+
previousAction: "page-prev",
|
|
61564
|
+
nextAction: "page-next",
|
|
61565
|
+
navigationLabel: strings2.pagination.navigation,
|
|
61566
|
+
currentLabel: formatPageString(
|
|
61567
|
+
strings2.pagination.pageLabel,
|
|
61568
|
+
pagination.current
|
|
61569
|
+
),
|
|
61570
|
+
previousTargetLabel: formatPageString(
|
|
61571
|
+
strings2.pagination.previousTargetPage,
|
|
61572
|
+
Math.max(pagination.current - 1, 1)
|
|
61573
|
+
),
|
|
61574
|
+
nextTargetLabel: formatPageString(
|
|
61575
|
+
strings2.pagination.nextTargetPage,
|
|
61576
|
+
Math.min(pagination.current + 1, pagination.total)
|
|
61577
|
+
)
|
|
61578
|
+
}) : void 0;
|
|
61579
|
+
const submitButton = templates.SubmitButton({
|
|
61580
|
+
id: stableId(id2, "submit"),
|
|
61581
|
+
actionName: ACTION_FIELD,
|
|
61582
|
+
value: "submit",
|
|
61583
|
+
label: submitLabel
|
|
61584
|
+
});
|
|
61585
|
+
const rendererHiddenFields = [
|
|
61586
|
+
hiddenFields,
|
|
61587
|
+
pageHiddenField(pagination?.current)
|
|
61588
|
+
].filter(Boolean).join("");
|
|
61589
|
+
const shortTextStyle = children.includes("data-fb-label-short") ? templates.ShortTextStyle({}) : "";
|
|
61573
61590
|
const formProperties = {
|
|
61574
61591
|
id: id2,
|
|
61575
61592
|
title: properties.title,
|
|
61576
61593
|
description: properties.description,
|
|
61577
61594
|
customExtensions: properties.customExtensions,
|
|
61595
|
+
hiddenFields: rendererHiddenFields,
|
|
61596
|
+
titleHtml,
|
|
61597
|
+
descriptionHtml,
|
|
61578
61598
|
after: renderHtml(properties.after),
|
|
61579
61599
|
before: renderHtml(properties.before),
|
|
61580
|
-
children
|
|
61600
|
+
children,
|
|
61581
61601
|
errors: renderHtml(properties.errors),
|
|
61582
61602
|
languageSelector: renderHtml(properties.languageSelector),
|
|
61583
61603
|
pagination,
|
|
61604
|
+
paginationHtml,
|
|
61605
|
+
shortTextStyle,
|
|
61584
61606
|
signature: renderHtml(properties.signature),
|
|
61585
|
-
submitLabel
|
|
61607
|
+
submitLabel,
|
|
61608
|
+
submitButton
|
|
61586
61609
|
};
|
|
61587
|
-
const fields = [hiddenFields, formFieldsTemplate(formProperties)].join("");
|
|
61588
61610
|
return renderTemplate(templates.Form, {
|
|
61589
61611
|
...formProperties,
|
|
61590
|
-
attributes: { id: id2, ...defaultAttributes(action2) }
|
|
61591
|
-
fields
|
|
61612
|
+
attributes: { id: id2, ...defaultAttributes(action2) }
|
|
61592
61613
|
});
|
|
61593
61614
|
}
|
|
61615
|
+
function formatPageString(template, page) {
|
|
61616
|
+
return template.replaceAll("{page}", String(page));
|
|
61617
|
+
}
|
|
61594
61618
|
function GroupList(properties) {
|
|
61595
61619
|
const { templates, token } = useHtmxTheme();
|
|
61596
61620
|
const renderHtml = useHtml();
|
|
@@ -61689,14 +61713,19 @@ function Label(properties) {
|
|
|
61689
61713
|
const strings2 = useStrings();
|
|
61690
61714
|
const children = renderHtml(properties.children);
|
|
61691
61715
|
const prefix2 = properties.prefix === void 0 ? void 0 : renderHtml(properties.prefix);
|
|
61692
|
-
const
|
|
61693
|
-
|
|
61694
|
-
|
|
61695
|
-
|
|
61696
|
-
|
|
61697
|
-
|
|
61698
|
-
|
|
61699
|
-
|
|
61716
|
+
const help = renderHtml(properties.help);
|
|
61717
|
+
const legal = renderHtml(properties.legal);
|
|
61718
|
+
const flyover = renderHtml(properties.flyover);
|
|
61719
|
+
const content = templates.LabelContent({
|
|
61720
|
+
children,
|
|
61721
|
+
prefix: prefix2,
|
|
61722
|
+
shortText: properties.shortText,
|
|
61723
|
+
required: properties.required,
|
|
61724
|
+
help,
|
|
61725
|
+
legal,
|
|
61726
|
+
flyover,
|
|
61727
|
+
hasShortText: properties.shortText !== void 0
|
|
61728
|
+
});
|
|
61700
61729
|
return renderTemplate(templates.Label, {
|
|
61701
61730
|
shortText: properties.shortText,
|
|
61702
61731
|
isExpanded: properties.isExpanded,
|
|
@@ -61710,10 +61739,11 @@ function Label(properties) {
|
|
|
61710
61739
|
content,
|
|
61711
61740
|
isLegend: properties.as === "legend",
|
|
61712
61741
|
isText: properties.as === "text",
|
|
61713
|
-
help
|
|
61714
|
-
legal
|
|
61715
|
-
flyover
|
|
61742
|
+
help,
|
|
61743
|
+
legal,
|
|
61744
|
+
flyover,
|
|
61716
61745
|
media: mediaHtml(
|
|
61746
|
+
templates,
|
|
61717
61747
|
properties.media,
|
|
61718
61748
|
strings2.inputs.attachmentLabel,
|
|
61719
61749
|
stableId(properties.id, "media")
|
|
@@ -61847,7 +61877,11 @@ function OptionDisplay(properties) {
|
|
|
61847
61877
|
const strings2 = useStrings();
|
|
61848
61878
|
return renderTemplate(templates.OptionDisplay, {
|
|
61849
61879
|
prefix: properties.prefix === void 0 ? void 0 : escapeHtml$1(properties.prefix),
|
|
61850
|
-
media: mediaHtml(
|
|
61880
|
+
media: mediaHtml(
|
|
61881
|
+
templates,
|
|
61882
|
+
properties.media,
|
|
61883
|
+
strings2.inputs.attachmentLabel
|
|
61884
|
+
),
|
|
61851
61885
|
attachmentLabel: strings2.inputs.attachmentLabel,
|
|
61852
61886
|
children: renderHtml(properties.children)
|
|
61853
61887
|
});
|
|
@@ -62177,7 +62211,7 @@ function renderStoreFields(store, templates, action2) {
|
|
|
62177
62211
|
const htmxTheme = {
|
|
62178
62212
|
templates,
|
|
62179
62213
|
token: store.token,
|
|
62180
|
-
hiddenFields: renderHiddenFieldsForStore(store),
|
|
62214
|
+
hiddenFields: renderHiddenFieldsForStore(store, templates),
|
|
62181
62215
|
activeTabValue: activeTab,
|
|
62182
62216
|
action: action2
|
|
62183
62217
|
};
|
|
@@ -62221,7 +62255,7 @@ function ensureServerRenderableRepeatQuestions(store) {
|
|
|
62221
62255
|
}
|
|
62222
62256
|
});
|
|
62223
62257
|
}
|
|
62224
|
-
function renderHiddenFieldsForStore(store) {
|
|
62258
|
+
function renderHiddenFieldsForStore(store, templates) {
|
|
62225
62259
|
const renderedNodes = /* @__PURE__ */ new Set([
|
|
62226
62260
|
...store.headerNodes,
|
|
62227
62261
|
...store.contentNodes,
|
|
@@ -62232,10 +62266,10 @@ function renderHiddenFieldsForStore(store) {
|
|
|
62232
62266
|
store.nodes.map(
|
|
62233
62267
|
(node) => renderHiddenFieldsForNode(node, [], renderedNodes.has(node))
|
|
62234
62268
|
).join(""),
|
|
62235
|
-
renderHiddenNodeIssues(store)
|
|
62269
|
+
renderHiddenNodeIssues(store, templates)
|
|
62236
62270
|
].join("");
|
|
62237
62271
|
}
|
|
62238
|
-
function renderHiddenNodeIssues(store) {
|
|
62272
|
+
function renderHiddenNodeIssues(store, templates) {
|
|
62239
62273
|
const messages = [];
|
|
62240
62274
|
store.walkNodes({
|
|
62241
62275
|
node(node) {
|
|
@@ -62245,7 +62279,11 @@ function renderHiddenNodeIssues(store) {
|
|
|
62245
62279
|
hiddenNodeIssues(node).map((issue) => getIssueMessage(issue)).filter((message) => message !== void 0).forEach((message) => messages.push(message));
|
|
62246
62280
|
}
|
|
62247
62281
|
});
|
|
62248
|
-
return
|
|
62282
|
+
return templates.Errors({
|
|
62283
|
+
id: `${store.token}__hidden-node-issues`,
|
|
62284
|
+
hasMessages: messages.length > 0,
|
|
62285
|
+
messages: messages.map((message) => ({ html: escapeHtml(message) }))
|
|
62286
|
+
});
|
|
62249
62287
|
}
|
|
62250
62288
|
function hiddenNodeIssues(node) {
|
|
62251
62289
|
if (node.issues.length > 0) {
|
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
{{!--
|
|
2
2
|
Template: Form
|
|
3
3
|
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders the outer form element and the top-level form sections.
|
|
6
|
+
|
|
4
7
|
Inputs:
|
|
5
8
|
- attributes: native form attributes generated by the renderer.
|
|
6
|
-
-
|
|
9
|
+
- hiddenFields: renderer-owned hidden protocol field html.
|
|
7
10
|
- customExtensions: source extension values, if supplied.
|
|
8
|
-
-
|
|
9
|
-
-
|
|
11
|
+
- shortTextStyle: responsive short-label CSS markup when short labels are present.
|
|
12
|
+
- titleHtml/descriptionHtml/languageSelector/errors/before/children/after/signature: rendered form sections.
|
|
13
|
+
- paginationHtml: rendered pagination controls, if available.
|
|
14
|
+
- submitButton: rendered submit control.
|
|
15
|
+
- title/description/pagination/submitLabel: source values for custom form templates.
|
|
10
16
|
--}}
|
|
11
17
|
<form{{{attrs attributes}}}>
|
|
12
|
-
{{{
|
|
18
|
+
{{{hiddenFields}}}
|
|
19
|
+
{{{shortTextStyle}}}
|
|
20
|
+
{{{titleHtml}}}
|
|
21
|
+
{{{descriptionHtml}}}
|
|
22
|
+
{{{languageSelector}}}
|
|
23
|
+
{{{errors}}}
|
|
24
|
+
{{{before}}}
|
|
25
|
+
{{{children}}}
|
|
26
|
+
{{{after}}}
|
|
27
|
+
{{{signature}}}
|
|
28
|
+
{{{paginationHtml}}}
|
|
29
|
+
{{{submitButton}}}
|
|
13
30
|
</form>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{{!--
|
|
2
|
+
Template: LabelContent
|
|
3
|
+
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders the inner label text, prefix, required marker, and support controls.
|
|
6
|
+
|
|
7
|
+
Inputs:
|
|
8
|
+
- children: rendered label text html.
|
|
9
|
+
- prefix: rendered prefix html, if supplied.
|
|
10
|
+
- shortText: responsive short label text, if supplied.
|
|
11
|
+
- required: true when required marker should render.
|
|
12
|
+
- help/legal/flyover: rendered extension control html.
|
|
13
|
+
- hasShortText: true when shortText is available.
|
|
14
|
+
--}}
|
|
15
|
+
{{#if prefix}}<span>{{{prefix}}} </span>{{/if}}{{#if hasShortText}}<span data-fb-label-full>{{{children}}}</span><span data-fb-label-short>{{shortText}}</span>{{else}}{{{children}}}{{/if}}{{#if required}}<span aria-hidden="true"> *</span>{{/if}}{{{help}}}{{{legal}}}{{{flyover}}}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{{!--
|
|
2
|
+
Template: Media
|
|
3
|
+
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders item or answer-option attachment media and fallback links.
|
|
6
|
+
|
|
7
|
+
Inputs:
|
|
8
|
+
- attachment: source attachment object.
|
|
9
|
+
- id: stable media id when available.
|
|
10
|
+
- label: accessible fallback label.
|
|
11
|
+
- source: resolved URL or data URL, if available.
|
|
12
|
+
- contentType: lower-cased attachment content type, if available.
|
|
13
|
+
- kind/isFallback/isImage/isAudio/isVideo/isLink: selected media rendering branch.
|
|
14
|
+
--}}
|
|
15
|
+
{{#if isFallback}}
|
|
16
|
+
<span>{{label}}</span>
|
|
17
|
+
{{/if}}
|
|
18
|
+
{{#if isImage}}
|
|
19
|
+
<img{{{attr "src" source}}}{{{attr "alt" label}}}>
|
|
20
|
+
{{/if}}
|
|
21
|
+
{{#if isAudio}}
|
|
22
|
+
<audio controls{{{attr "id" id}}}{{{attr "src" source}}}></audio>
|
|
23
|
+
{{/if}}
|
|
24
|
+
{{#if isVideo}}
|
|
25
|
+
<video controls{{{attr "id" id}}}{{{attr "src" source}}}></video>
|
|
26
|
+
{{/if}}
|
|
27
|
+
{{#if isLink}}
|
|
28
|
+
<a{{{attr "id" id}}}{{{attr "href" source}}} target="_blank" rel="noreferrer">{{label}}</a>
|
|
29
|
+
{{/if}}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{{!--
|
|
2
|
+
Template: Pagination
|
|
3
|
+
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders page navigation controls for paginated questionnaires.
|
|
6
|
+
|
|
7
|
+
Inputs:
|
|
8
|
+
- current/total: current page number and total page count.
|
|
9
|
+
- disabledPrev/disabledNext: whether each navigation action is unavailable.
|
|
10
|
+
- actionName: form action field name.
|
|
11
|
+
- previousAction/nextAction: submitted action values for page navigation.
|
|
12
|
+
- previousId/nextId: stable button ids.
|
|
13
|
+
- previousLabel/nextLabel: visible button labels.
|
|
14
|
+
- navigationLabel/currentLabel/previousTargetLabel/nextTargetLabel: accessible pagination labels.
|
|
15
|
+
--}}
|
|
16
|
+
<nav>
|
|
17
|
+
{{#unless disabledPrev}}
|
|
18
|
+
<button type="submit"{{{attr "id" previousId}}}{{{attr "name" actionName}}}{{{attr "value" previousAction}}}>{{previousLabel}}</button>
|
|
19
|
+
{{/unless}}
|
|
20
|
+
<span>{{current}} / {{total}}</span>
|
|
21
|
+
{{#unless disabledNext}}
|
|
22
|
+
<button type="submit"{{{attr "id" nextId}}}{{{attr "name" actionName}}}{{{attr "value" nextAction}}}>{{nextLabel}}</button>
|
|
23
|
+
{{/unless}}
|
|
24
|
+
</nav>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{{!--
|
|
2
|
+
Template: ShortTextStyle
|
|
3
|
+
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders responsive CSS that swaps long labels for short labels on narrow screens.
|
|
6
|
+
|
|
7
|
+
Inputs:
|
|
8
|
+
- no inputs.
|
|
9
|
+
--}}
|
|
10
|
+
<style>[data-fb-label-short]{display:none}@media (max-width:40rem){[data-fb-label-full]{display:none}[data-fb-label-short]{display:inline}}</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{{!--
|
|
2
|
+
Template: SubmitButton
|
|
3
|
+
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders the main form submit action.
|
|
6
|
+
|
|
7
|
+
Inputs:
|
|
8
|
+
- id: stable submit button id.
|
|
9
|
+
- actionName: form action field name.
|
|
10
|
+
- value: submitted action value.
|
|
11
|
+
- label: visible submit label.
|
|
12
|
+
--}}
|
|
13
|
+
<button type="submit"{{{attr "id" id}}}{{{attr "name" actionName}}}{{{attr "value" value}}}>{{label}}</button>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{{!--
|
|
2
2
|
Template: Table
|
|
3
3
|
|
|
4
|
+
Purpose:
|
|
5
|
+
- Renders matrix-style controls from prepared columns, rows, and cells.
|
|
6
|
+
|
|
4
7
|
Inputs:
|
|
5
8
|
- hasRowHeader: true when rows need a header column.
|
|
6
9
|
- columns: column items with token, content, errors, width, widthStyle, and isLoading.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formbox/htmx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Server-rendered HTMX HTML renderer for Formbox FHIR Questionnaires",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "tsc -b ./tsconfig.lib.json && vite build",
|
|
48
|
-
"demo": "bun run ./demo/server.ts",
|
|
49
|
-
"dev": "bun run ./demo/server.ts",
|
|
48
|
+
"demo": "bun run build && bun ./demo/server.ts",
|
|
49
|
+
"dev": "bun run build && bun ./demo/server.ts",
|
|
50
50
|
"lint": "eslint .",
|
|
51
51
|
"test:e2e": "pnpm run build && playwright test e2e",
|
|
52
52
|
"typecheck": "tsc --noEmit -p tsconfig.lib.json",
|