@formbox/htmx 0.5.0 → 0.6.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.
Files changed (49) hide show
  1. package/dist/index.d.ts +72 -3
  2. package/dist/index.js +110 -54
  3. package/dist/templates/AnswerList.html.hbs +3 -0
  4. package/dist/templates/AnswerScaffold.html.hbs +3 -0
  5. package/dist/templates/Checkbox.html.hbs +3 -0
  6. package/dist/templates/CheckboxList.html.hbs +3 -0
  7. package/dist/templates/CustomOptionForm.html.hbs +3 -0
  8. package/dist/templates/DateInput.html.hbs +3 -0
  9. package/dist/templates/DateTimeInput.html.hbs +3 -0
  10. package/dist/templates/DisplayRenderer.html.hbs +3 -0
  11. package/dist/templates/Errors.html.hbs +3 -0
  12. package/dist/templates/FileInput.html.hbs +3 -0
  13. package/dist/templates/Flyover.html.hbs +3 -0
  14. package/dist/templates/Footer.html.hbs +3 -0
  15. package/dist/templates/Form.html.hbs +22 -4
  16. package/dist/templates/FormDescription.html.hbs +10 -0
  17. package/dist/templates/FormTitle.html.hbs +10 -0
  18. package/dist/templates/GroupList.html.hbs +3 -0
  19. package/dist/templates/GroupScaffold.html.hbs +3 -0
  20. package/dist/templates/Header.html.hbs +3 -0
  21. package/dist/templates/Help.html.hbs +3 -0
  22. package/dist/templates/InputGroup.html.hbs +3 -0
  23. package/dist/templates/Label.html.hbs +3 -0
  24. package/dist/templates/LabelContent.html.hbs +15 -0
  25. package/dist/templates/LanguageSelector.html.hbs +3 -0
  26. package/dist/templates/Legal.html.hbs +3 -0
  27. package/dist/templates/Link.html.hbs +3 -0
  28. package/dist/templates/Media.html.hbs +29 -0
  29. package/dist/templates/MultiSelectInput.html.hbs +3 -0
  30. package/dist/templates/NumberInput.html.hbs +3 -0
  31. package/dist/templates/OptionDisplay.html.hbs +3 -0
  32. package/dist/templates/OptionsLoading.html.hbs +3 -0
  33. package/dist/templates/Pagination.html.hbs +24 -0
  34. package/dist/templates/QuestionScaffold.html.hbs +3 -0
  35. package/dist/templates/RadioButton.html.hbs +3 -0
  36. package/dist/templates/RadioButtonList.html.hbs +3 -0
  37. package/dist/templates/SelectInput.html.hbs +3 -0
  38. package/dist/templates/ShortTextStyle.html.hbs +10 -0
  39. package/dist/templates/SignatureInput.html.hbs +3 -0
  40. package/dist/templates/SliderInput.html.hbs +3 -0
  41. package/dist/templates/SpinnerInput.html.hbs +3 -0
  42. package/dist/templates/Stack.html.hbs +3 -0
  43. package/dist/templates/SubmitButton.html.hbs +13 -0
  44. package/dist/templates/TabContainer.html.hbs +3 -0
  45. package/dist/templates/Table.html.hbs +3 -0
  46. package/dist/templates/TextArea.html.hbs +3 -0
  47. package/dist/templates/TextInput.html.hbs +3 -0
  48. package/dist/templates/TimeInput.html.hbs +3 -0
  49. package/package.json +5 -5
package/dist/index.d.ts CHANGED
@@ -285,6 +285,10 @@ export declare type FooterTemplateProperties = Omit<TemplateBase<FooterPropertie
285
285
  readonly children: string;
286
286
  };
287
287
 
288
+ export declare type FormDescriptionTemplateProperties = {
289
+ readonly description: string;
290
+ };
291
+
288
292
  declare type FormFieldsProperties = Omit<FormTemplateProperties, "attributes" | "fields">;
289
293
 
290
294
  export declare function formFieldsTemplate(properties: FormFieldsProperties): string;
@@ -320,11 +324,21 @@ export declare type FormTemplateProperties = Omit<TemplateBase<FormProperties>,
320
324
  readonly children: string;
321
325
  readonly errors?: string | undefined;
322
326
  readonly fields: string;
327
+ readonly hiddenFields: string;
323
328
  readonly attributes: HtmlAttributes;
329
+ readonly titleHtml?: string | undefined;
330
+ readonly descriptionHtml?: string | undefined;
324
331
  readonly languageSelector?: string | undefined;
325
332
  readonly pagination?: TemplateFormPagination | undefined;
333
+ readonly paginationHtml?: string | undefined;
334
+ readonly shortTextStyle: string;
326
335
  readonly signature?: string | undefined;
327
336
  readonly submitLabel: string;
337
+ readonly submitButton: string;
338
+ };
339
+
340
+ export declare type FormTitleTemplateProperties = {
341
+ readonly title: string;
328
342
  };
329
343
 
330
344
  declare type GroupListProperties = {
@@ -432,6 +446,17 @@ export declare function isPreservedOptionToken(token: string): boolean;
432
446
 
433
447
  declare type LabelAs = "legend" | "label" | "text";
434
448
 
449
+ export declare type LabelContentTemplateProperties = {
450
+ readonly children: string;
451
+ readonly prefix?: string | undefined;
452
+ readonly shortText?: string | undefined;
453
+ readonly required?: boolean | undefined;
454
+ readonly help?: string | undefined;
455
+ readonly legal?: string | undefined;
456
+ readonly flyover?: string | undefined;
457
+ readonly hasShortText: boolean;
458
+ };
459
+
435
460
  declare type LabelProperties = {
436
461
  prefix?: ReactNode;
437
462
  shortText?: string | undefined;
@@ -519,7 +544,23 @@ export declare function loadDefaultTemplates(): Promise<RequiredTemplates>;
519
544
 
520
545
  export declare function loadTemplates(directory: string | URL): Promise<Templates>;
521
546
 
522
- export declare function mediaHtml(attachment: Attachment | undefined, fallbackLabel: string, id?: string | undefined): string;
547
+ export declare function mediaHtml(templates: Pick<RequiredTemplates, "Media">, attachment: Attachment | undefined, fallbackLabel: string, id?: string | undefined): string;
548
+
549
+ export declare type MediaKind = "fallback" | "image" | "audio" | "video" | "link";
550
+
551
+ export declare type MediaTemplateProperties = {
552
+ readonly attachment: Attachment;
553
+ readonly id?: string | undefined;
554
+ readonly label: string;
555
+ readonly source?: string | undefined;
556
+ readonly contentType?: string | undefined;
557
+ readonly kind: MediaKind;
558
+ readonly isFallback: boolean;
559
+ readonly isImage: boolean;
560
+ readonly isAudio: boolean;
561
+ readonly isVideo: boolean;
562
+ readonly isLink: boolean;
563
+ };
523
564
 
524
565
  declare type MultiSelectInputProperties = {
525
566
  options: readonly OptionItem[];
@@ -619,6 +660,18 @@ export declare function optionValueName(path: NodePath, token: string): string;
619
660
 
620
661
  export declare const PAGE_FIELD = "fb[page]";
621
662
 
663
+ export declare function pageHiddenField(currentPage: number | undefined): string;
664
+
665
+ export declare type PaginationTemplateProperties = TemplateFormPagination & {
666
+ readonly actionName: string;
667
+ readonly previousAction: "page-prev";
668
+ readonly nextAction: "page-next";
669
+ readonly navigationLabel: string;
670
+ readonly currentLabel: string;
671
+ readonly previousTargetLabel: string;
672
+ readonly nextTargetLabel: string;
673
+ };
674
+
622
675
  export declare function pathControlId(token: string, path: NodePath | undefined, ...parts: Array<string | number | undefined>): string | undefined;
623
676
 
624
677
  declare type PlaceholderString<Key extends string> = `${string}{${Key}}${string}`;
@@ -800,6 +853,8 @@ export declare type SelectOptionTemplateItem = TemplateOptionItem & {
800
853
  readonly selected: boolean;
801
854
  };
802
855
 
856
+ export declare type ShortTextStyleTemplateProperties = Record<string, never>;
857
+
803
858
  declare type SignatureInputProperties = {
804
859
  value: string | undefined;
805
860
  id: string;
@@ -1001,6 +1056,13 @@ declare type Strings = {
1001
1056
 
1002
1057
  export declare const SUBMIT_ATTEMPTED_FIELD = "fb[submitAttempted]";
1003
1058
 
1059
+ export declare type SubmitButtonTemplateProperties = {
1060
+ readonly id?: string | undefined;
1061
+ readonly actionName: string;
1062
+ readonly value: "submit";
1063
+ readonly label: string;
1064
+ };
1065
+
1004
1066
  declare type TabContainerProperties = {
1005
1067
  path?: NodePath | undefined;
1006
1068
  header?: ReactNode;
@@ -1090,13 +1152,13 @@ export declare type TemplateFormPagination = Omit<FormPagination, "onNext" | "on
1090
1152
 
1091
1153
  export declare type TemplateName = keyof Templates;
1092
1154
 
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"];
1155
+ 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
1156
 
1095
1157
  export declare type TemplateOptionItem = Omit<OptionItem, "label"> & {
1096
1158
  readonly label: string;
1097
1159
  };
1098
1160
 
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;
1161
+ 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
1162
 
1101
1163
  export declare interface Templates {
1102
1164
  readonly TextInput?: Template<TextInputTemplateProperties> | undefined;
@@ -1115,8 +1177,10 @@ export declare interface Templates {
1115
1177
  readonly CheckboxList?: Template<CheckboxListTemplateProperties> | undefined;
1116
1178
  readonly MultiSelectInput?: Template<MultiSelectInputTemplateProperties> | undefined;
1117
1179
  readonly CustomOptionForm?: Template<CustomOptionFormTemplateProperties> | undefined;
1180
+ readonly Media?: Template<MediaTemplateProperties> | undefined;
1118
1181
  readonly Errors?: Template<ErrorsTemplateProperties> | undefined;
1119
1182
  readonly Label?: Template<LabelTemplateProperties> | undefined;
1183
+ readonly LabelContent?: Template<LabelContentTemplateProperties> | undefined;
1120
1184
  readonly QuestionScaffold?: Template<QuestionScaffoldTemplateProperties> | undefined;
1121
1185
  readonly OptionsLoading?: Template<OptionsLoadingTemplateProperties> | undefined;
1122
1186
  readonly Help?: Template<HelpTemplateProperties> | undefined;
@@ -1124,6 +1188,11 @@ export declare interface Templates {
1124
1188
  readonly Flyover?: Template<FlyoverTemplateProperties> | undefined;
1125
1189
  readonly Header?: Template<HeaderTemplateProperties> | undefined;
1126
1190
  readonly Footer?: Template<FooterTemplateProperties> | undefined;
1191
+ readonly FormTitle?: Template<FormTitleTemplateProperties> | undefined;
1192
+ readonly FormDescription?: Template<FormDescriptionTemplateProperties> | undefined;
1193
+ readonly Pagination?: Template<PaginationTemplateProperties> | undefined;
1194
+ readonly SubmitButton?: Template<SubmitButtonTemplateProperties> | undefined;
1195
+ readonly ShortTextStyle?: Template<ShortTextStyleTemplateProperties> | undefined;
1127
1196
  readonly Form?: Template<FormTemplateProperties> | undefined;
1128
1197
  readonly Stack?: Template<StackTemplateProperties> | undefined;
1129
1198
  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,44 +59693,47 @@ 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
- if (source === void 0) {
59697
- return `<span>${escapeHtml$1(label)}</span>`;
59698
- }
59699
- if (contentType?.startsWith("image/")) {
59700
- return `<img${attribute("src", source)}${attribute("alt", label)}>`;
59701
- }
59702
- if (contentType?.startsWith("audio/")) {
59703
- return `<audio controls${attribute("id", id2)}${attribute("src", source)}></audio>`;
59704
- }
59705
- if (contentType?.startsWith("video/")) {
59706
- return `<video controls${attribute("id", id2)}${attribute("src", source)}></video>`;
59707
- }
59708
- return `<a${attribute("id", id2)}${attribute("href", source)} target="_blank" rel="noreferrer">${escapeHtml$1(label)}</a>`;
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
59718
  function formFieldsTemplate(properties) {
59711
- const shortTextStyle = properties.children.includes("data-fb-label-short") ? "<style>[data-fb-label-short]{display:none}@media (max-width:40rem){[data-fb-label-full]{display:none}[data-fb-label-short]{display:inline}}</style>" : void 0;
59712
59719
  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>` : "",
59720
+ properties.hiddenFields,
59721
+ properties.shortTextStyle,
59722
+ properties.titleHtml ?? "",
59723
+ properties.descriptionHtml ?? "",
59717
59724
  properties.languageSelector ?? "",
59718
59725
  properties.errors ?? "",
59719
59726
  properties.before ?? "",
59720
59727
  properties.children,
59721
59728
  properties.after ?? "",
59722
59729
  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>`
59730
+ properties.paginationHtml ?? "",
59731
+ properties.submitButton
59725
59732
  ].join("");
59726
59733
  }
59734
+ function pageHiddenField(currentPage) {
59735
+ return `<input type="hidden" name="${PAGE_FIELD}" value="${String(currentPage ?? 1)}">`;
59736
+ }
59727
59737
  function fieldAttributes$1(path2, field) {
59728
59738
  if (field === "signature") {
59729
59739
  const signaturePath = path2 ?? [];
@@ -59861,19 +59871,6 @@ function defaultAttributes(action2) {
59861
59871
  "hx-include": "closest form"
59862
59872
  };
59863
59873
  }
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
59874
  function tableCell(cell, renderHtml) {
59878
59875
  return {
59879
59876
  token: cell.token,
@@ -61560,6 +61557,8 @@ function Form(properties) {
61560
61557
  const renderHtml = useHtml();
61561
61558
  const strings2 = useStrings();
61562
61559
  const id2 = properties.id ?? token;
61560
+ const submitLabel = strings2.form.submit;
61561
+ const children = renderHtml(properties.children);
61563
61562
  const pagination = properties.pagination ? {
61564
61563
  current: properties.pagination.current,
61565
61564
  total: properties.pagination.total,
@@ -61570,27 +61569,70 @@ function Form(properties) {
61570
61569
  previousId: stableId(id2, "pagination", "previous"),
61571
61570
  previousLabel: strings2.pagination.previous
61572
61571
  } : void 0;
61572
+ const titleHtml = properties.title ? templates.FormTitle({ title: properties.title }) : void 0;
61573
+ const descriptionHtml = properties.description ? templates.FormDescription({
61574
+ description: properties.description
61575
+ }) : void 0;
61576
+ const paginationHtml = pagination ? templates.Pagination({
61577
+ ...pagination,
61578
+ actionName: ACTION_FIELD,
61579
+ previousAction: "page-prev",
61580
+ nextAction: "page-next",
61581
+ navigationLabel: strings2.pagination.navigation,
61582
+ currentLabel: formatPageString(
61583
+ strings2.pagination.pageLabel,
61584
+ pagination.current
61585
+ ),
61586
+ previousTargetLabel: formatPageString(
61587
+ strings2.pagination.previousTargetPage,
61588
+ Math.max(pagination.current - 1, 1)
61589
+ ),
61590
+ nextTargetLabel: formatPageString(
61591
+ strings2.pagination.nextTargetPage,
61592
+ Math.min(pagination.current + 1, pagination.total)
61593
+ )
61594
+ }) : void 0;
61595
+ const submitButton = templates.SubmitButton({
61596
+ id: stableId(id2, "submit"),
61597
+ actionName: ACTION_FIELD,
61598
+ value: "submit",
61599
+ label: submitLabel
61600
+ });
61601
+ const rendererHiddenFields = [
61602
+ hiddenFields,
61603
+ pageHiddenField(pagination?.current)
61604
+ ].filter(Boolean).join("");
61605
+ const shortTextStyle = children.includes("data-fb-label-short") ? templates.ShortTextStyle({}) : "";
61573
61606
  const formProperties = {
61574
61607
  id: id2,
61575
61608
  title: properties.title,
61576
61609
  description: properties.description,
61577
61610
  customExtensions: properties.customExtensions,
61611
+ hiddenFields: rendererHiddenFields,
61612
+ titleHtml,
61613
+ descriptionHtml,
61578
61614
  after: renderHtml(properties.after),
61579
61615
  before: renderHtml(properties.before),
61580
- children: renderHtml(properties.children),
61616
+ children,
61581
61617
  errors: renderHtml(properties.errors),
61582
61618
  languageSelector: renderHtml(properties.languageSelector),
61583
61619
  pagination,
61620
+ paginationHtml,
61621
+ shortTextStyle,
61584
61622
  signature: renderHtml(properties.signature),
61585
- submitLabel: strings2.form.submit
61623
+ submitLabel,
61624
+ submitButton
61586
61625
  };
61587
- const fields = [hiddenFields, formFieldsTemplate(formProperties)].join("");
61626
+ const fields = formFieldsTemplate(formProperties);
61588
61627
  return renderTemplate(templates.Form, {
61589
61628
  ...formProperties,
61590
61629
  attributes: { id: id2, ...defaultAttributes(action2) },
61591
61630
  fields
61592
61631
  });
61593
61632
  }
61633
+ function formatPageString(template, page) {
61634
+ return template.replaceAll("{page}", String(page));
61635
+ }
61594
61636
  function GroupList(properties) {
61595
61637
  const { templates, token } = useHtmxTheme();
61596
61638
  const renderHtml = useHtml();
@@ -61689,14 +61731,19 @@ function Label(properties) {
61689
61731
  const strings2 = useStrings();
61690
61732
  const children = renderHtml(properties.children);
61691
61733
  const prefix2 = properties.prefix === void 0 ? void 0 : renderHtml(properties.prefix);
61692
- const content = [
61693
- prefix2 === void 0 ? "" : `<span>${prefix2} </span>`,
61694
- properties.shortText === void 0 ? children : `<span data-fb-label-full>${children}</span><span data-fb-label-short>${escapeHtml$1(properties.shortText)}</span>`,
61695
- properties.required ? '<span aria-hidden="true"> *</span>' : "",
61696
- renderHtml(properties.help),
61697
- renderHtml(properties.legal),
61698
- renderHtml(properties.flyover)
61699
- ].join("");
61734
+ const help = renderHtml(properties.help);
61735
+ const legal = renderHtml(properties.legal);
61736
+ const flyover = renderHtml(properties.flyover);
61737
+ const content = templates.LabelContent({
61738
+ children,
61739
+ prefix: prefix2,
61740
+ shortText: properties.shortText,
61741
+ required: properties.required,
61742
+ help,
61743
+ legal,
61744
+ flyover,
61745
+ hasShortText: properties.shortText !== void 0
61746
+ });
61700
61747
  return renderTemplate(templates.Label, {
61701
61748
  shortText: properties.shortText,
61702
61749
  isExpanded: properties.isExpanded,
@@ -61710,10 +61757,11 @@ function Label(properties) {
61710
61757
  content,
61711
61758
  isLegend: properties.as === "legend",
61712
61759
  isText: properties.as === "text",
61713
- help: renderHtml(properties.help),
61714
- legal: renderHtml(properties.legal),
61715
- flyover: renderHtml(properties.flyover),
61760
+ help,
61761
+ legal,
61762
+ flyover,
61716
61763
  media: mediaHtml(
61764
+ templates,
61717
61765
  properties.media,
61718
61766
  strings2.inputs.attachmentLabel,
61719
61767
  stableId(properties.id, "media")
@@ -61847,7 +61895,11 @@ function OptionDisplay(properties) {
61847
61895
  const strings2 = useStrings();
61848
61896
  return renderTemplate(templates.OptionDisplay, {
61849
61897
  prefix: properties.prefix === void 0 ? void 0 : escapeHtml$1(properties.prefix),
61850
- media: mediaHtml(properties.media, strings2.inputs.attachmentLabel),
61898
+ media: mediaHtml(
61899
+ templates,
61900
+ properties.media,
61901
+ strings2.inputs.attachmentLabel
61902
+ ),
61851
61903
  attachmentLabel: strings2.inputs.attachmentLabel,
61852
61904
  children: renderHtml(properties.children)
61853
61905
  });
@@ -62177,7 +62229,7 @@ function renderStoreFields(store, templates, action2) {
62177
62229
  const htmxTheme = {
62178
62230
  templates,
62179
62231
  token: store.token,
62180
- hiddenFields: renderHiddenFieldsForStore(store),
62232
+ hiddenFields: renderHiddenFieldsForStore(store, templates),
62181
62233
  activeTabValue: activeTab,
62182
62234
  action: action2
62183
62235
  };
@@ -62221,7 +62273,7 @@ function ensureServerRenderableRepeatQuestions(store) {
62221
62273
  }
62222
62274
  });
62223
62275
  }
62224
- function renderHiddenFieldsForStore(store) {
62276
+ function renderHiddenFieldsForStore(store, templates) {
62225
62277
  const renderedNodes = /* @__PURE__ */ new Set([
62226
62278
  ...store.headerNodes,
62227
62279
  ...store.contentNodes,
@@ -62232,10 +62284,10 @@ function renderHiddenFieldsForStore(store) {
62232
62284
  store.nodes.map(
62233
62285
  (node) => renderHiddenFieldsForNode(node, [], renderedNodes.has(node))
62234
62286
  ).join(""),
62235
- renderHiddenNodeIssues(store)
62287
+ renderHiddenNodeIssues(store, templates)
62236
62288
  ].join("");
62237
62289
  }
62238
- function renderHiddenNodeIssues(store) {
62290
+ function renderHiddenNodeIssues(store, templates) {
62239
62291
  const messages = [];
62240
62292
  store.walkNodes({
62241
62293
  node(node) {
@@ -62245,7 +62297,11 @@ function renderHiddenNodeIssues(store) {
62245
62297
  hiddenNodeIssues(node).map((issue) => getIssueMessage(issue)).filter((message) => message !== void 0).forEach((message) => messages.push(message));
62246
62298
  }
62247
62299
  });
62248
- return messages.length === 0 ? "" : `<ul class="fb-errors">${messages.map((message) => `<li>${escapeHtml(message)}</li>`).join("")}</ul>`;
62300
+ return templates.Errors({
62301
+ id: `${store.token}__hidden-node-issues`,
62302
+ hasMessages: messages.length > 0,
62303
+ messages: messages.map((message) => ({ html: escapeHtml(message) }))
62304
+ });
62249
62305
  }
62250
62306
  function hiddenNodeIssues(node) {
62251
62307
  if (node.issues.length > 0) {
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: AnswerList
3
3
 
4
+ Purpose:
5
+ - Renders a repeated answer collection and its add-answer action.
6
+
4
7
  Inputs:
5
8
  - children: rendered repeated answer rows.
6
9
  - hasCount/countName/count: hidden occurrence count state.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: AnswerScaffold
3
3
 
4
+ Purpose:
5
+ - Renders one answer instance, including its controls, errors, and remove action.
6
+
4
7
  Inputs:
5
8
  - control: rendered answer control.
6
9
  - errors: rendered answer errors.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Checkbox
3
3
 
4
+ Purpose:
5
+ - Renders one checkbox answer option input and its visible label.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - checkedValue/uncheckedValue: submitted values for checked and unchecked states.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: CheckboxList
3
3
 
4
+ Purpose:
5
+ - Renders a repeating choice question as a checkbox option list.
6
+
4
7
  Inputs:
5
8
  - id: fieldset id.
6
9
  - options: items with id, token, label, selected, disabled, and hiddenInput.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: CustomOptionForm
3
3
 
4
+ Purpose:
5
+ - Renders the inline custom/open-choice value editor and its actions.
6
+
4
7
  Inputs:
5
8
  - content: rendered custom option fields.
6
9
  - errors: rendered validation errors.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: DateInput
3
3
 
4
+ Purpose:
5
+ - Renders a date answer control and its native field constraints.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - inputType: date or text fallback input type.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: DateTimeInput
3
3
 
4
+ Purpose:
5
+ - Renders a date-time answer control and its preserved baseline value.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - inputType: datetime-local or text fallback input type.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: DisplayRenderer
3
3
 
4
+ Purpose:
5
+ - Renders display-only item content.
6
+
4
7
  Inputs:
5
8
  - linkId: display item link id.
6
9
  - children: rendered display html.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Errors
3
3
 
4
+ Purpose:
5
+ - Renders visible validation or rendering issue messages for a field or form surface.
6
+
4
7
  Inputs:
5
8
  - id: error container id.
6
9
  - messages: escaped validation messages as html entries.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: FileInput
3
3
 
4
+ Purpose:
5
+ - Renders an attachment file control, preserved value, and clear action.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value/hiddenValue: current attachment and hidden JSON mirror.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Flyover
3
3
 
4
+ Purpose:
5
+ - Renders flyover guidance as an accessible disclosure control.
6
+
4
7
  Inputs:
5
8
  - id: tooltip id.
6
9
  - children: rendered flyover content.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Footer
3
3
 
4
+ Purpose:
5
+ - Renders footer display content.
6
+
4
7
  Inputs:
5
8
  - linkId: item link id.
6
9
  - children: rendered footer content.
@@ -1,13 +1,31 @@
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
- - fields: full rendered field html.
9
+ - hiddenFields: renderer-owned hidden protocol field html.
10
+ - fields: legacy full rendered field html.
7
11
  - customExtensions: source extension values, if supplied.
8
- - title/description/languageSelector/errors/before/children/after/signature: source sections already included in fields.
9
- - pagination/submitLabel: source action state already included in fields.
12
+ - shortTextStyle: responsive short-label CSS markup when short labels are present.
13
+ - titleHtml/descriptionHtml/languageSelector/errors/before/children/after/signature: rendered form sections.
14
+ - paginationHtml: rendered pagination controls, if available.
15
+ - submitButton: rendered submit control.
16
+ - title/description/pagination/submitLabel: source values for custom form templates.
10
17
  --}}
11
18
  <form{{{attrs attributes}}}>
12
- {{{fields}}}
19
+ {{{hiddenFields}}}
20
+ {{{shortTextStyle}}}
21
+ {{{titleHtml}}}
22
+ {{{descriptionHtml}}}
23
+ {{{languageSelector}}}
24
+ {{{errors}}}
25
+ {{{before}}}
26
+ {{{children}}}
27
+ {{{after}}}
28
+ {{{signature}}}
29
+ {{{paginationHtml}}}
30
+ {{{submitButton}}}
13
31
  </form>
@@ -0,0 +1,10 @@
1
+ {{!--
2
+ Template: FormDescription
3
+
4
+ Purpose:
5
+ - Renders the questionnaire description slot.
6
+
7
+ Inputs:
8
+ - description: localized questionnaire description text.
9
+ --}}
10
+ <p>{{description}}</p>
@@ -0,0 +1,10 @@
1
+ {{!--
2
+ Template: FormTitle
3
+
4
+ Purpose:
5
+ - Renders the questionnaire title slot.
6
+
7
+ Inputs:
8
+ - title: localized questionnaire title text.
9
+ --}}
10
+ <h1>{{title}}</h1>
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: GroupList
3
3
 
4
+ Purpose:
5
+ - Renders a repeated group collection and its add-group action.
6
+
4
7
  Inputs:
5
8
  - linkId: repeated group link id.
6
9
  - header/errors/children: rendered group list sections.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: GroupScaffold
3
3
 
4
+ Purpose:
5
+ - Renders one group instance, including header, errors, children, and remove action.
6
+
4
7
  Inputs:
5
8
  - linkId: group link id.
6
9
  - header/children/expandedChildren/errors/signature: rendered group sections.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Header
3
3
 
4
+ Purpose:
5
+ - Renders header display content.
6
+
4
7
  Inputs:
5
8
  - linkId: item link id.
6
9
  - children: rendered header content.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Help
3
3
 
4
+ Purpose:
5
+ - Renders help text as an accessible disclosure control.
6
+
4
7
  Inputs:
5
8
  - id: tooltip id.
6
9
  - children: rendered help content.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: InputGroup
3
3
 
4
+ Purpose:
5
+ - Renders grouped input fragments that belong to one answer control.
6
+
4
7
  Inputs:
5
8
  - children: rendered grouped input controls.
6
9
  - spans: source layout spans, if supplied.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Label
3
3
 
4
+ Purpose:
5
+ - Renders the label, legend, or text wrapper around item label content.
6
+
4
7
  Inputs:
5
8
  - id/htmlFor: label id and target control id.
6
9
  - as/isLegend/isText: rendered label element kind.
@@ -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}}}
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: LanguageSelector
3
3
 
4
+ Purpose:
5
+ - Renders the form language selection control.
6
+
4
7
  Inputs:
5
8
  - id: select id.
6
9
  - name: generated language field name.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Legal
3
3
 
4
+ Purpose:
5
+ - Renders legal text as an accessible disclosure control.
6
+
4
7
  Inputs:
5
8
  - id: dialog id.
6
9
  - children: rendered legal content.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Link
3
3
 
4
+ Purpose:
5
+ - Renders hyperlink display content.
6
+
4
7
  Inputs:
5
8
  - id: link id.
6
9
  - href: link target.
@@ -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}}
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: MultiSelectInput
3
3
 
4
+ Purpose:
5
+ - Renders a searchable multi-select choice control and preserved selections.
6
+
4
7
  Inputs:
5
8
  - id: fieldset id.
6
9
  - options: items with id, token, label, selected, disabled, and hiddenInput.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: NumberInput
3
3
 
4
+ Purpose:
5
+ - Renders a numeric answer control with unit and comparator context.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value/inputValue: numeric answer value prepared for the native input.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: OptionDisplay
3
3
 
4
+ Purpose:
5
+ - Renders the visible content for one answer option.
6
+
4
7
  Inputs:
5
8
  - children: rendered option text.
6
9
  - prefix: optional option prefix.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: OptionsLoading
3
3
 
4
+ Purpose:
5
+ - Renders the loading indicator for asynchronously resolved answer options.
6
+
4
7
  Inputs:
5
8
  - isLoading: true when options are loading.
6
9
  - loadingLabel: loading message text.
@@ -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>
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: QuestionScaffold
3
3
 
4
+ Purpose:
5
+ - Renders a question wrapper with header, errors, answer controls, and expanded content.
6
+
4
7
  Inputs:
5
8
  - linkId: question link id.
6
9
  - header/children/expandedChildren/errors/signature: rendered question sections.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: RadioButton
3
3
 
4
+ Purpose:
5
+ - Renders one radio answer option input and its visible label.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - groupName: source radio group name, if supplied.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: RadioButtonList
3
3
 
4
+ Purpose:
5
+ - Renders a single-select choice question as a radio option list.
6
+
4
7
  Inputs:
5
8
  - id: fieldset id.
6
9
  - options: items with id, token, label, checked, and disabled.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: SelectInput
3
3
 
4
+ Purpose:
5
+ - Renders a select/open-choice dropdown with search and custom-option controls.
6
+
4
7
  Inputs:
5
8
  - id: select id.
6
9
  - value: selected option token.
@@ -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>
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: SignatureInput
3
3
 
4
+ Purpose:
5
+ - Renders a signature answer control and its submitted value field.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value/inputValue: serialized signature value.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: SliderInput
3
3
 
4
+ Purpose:
5
+ - Renders a numeric answer as a range slider.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value/inputValue: numeric answer value prepared for the native range input.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: SpinnerInput
3
3
 
4
+ Purpose:
5
+ - Renders a numeric answer as a stepper-style input.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value/inputValue: numeric answer value prepared for the native number input.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: Stack
3
3
 
4
+ Purpose:
5
+ - Renders a generic stack of child content.
6
+
4
7
  Inputs:
5
8
  - children: rendered stacked content.
6
9
  --}}
@@ -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: TabContainer
3
3
 
4
+ Purpose:
5
+ - Renders tabbed group navigation and the active panel content.
6
+
4
7
  Inputs:
5
8
  - linkId: tab group link id.
6
9
  - header/errors: rendered tab group sections.
@@ -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.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: TextArea
3
3
 
4
+ Purpose:
5
+ - Renders a multi-line text answer control.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value: submitted text value.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: TextInput
3
3
 
4
+ Purpose:
5
+ - Renders a scalar text-style answer control.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - type/inputType: requested and rendered native input type.
@@ -1,6 +1,9 @@
1
1
  {{!--
2
2
  Template: TimeInput
3
3
 
4
+ Purpose:
5
+ - Renders a time answer control.
6
+
4
7
  Inputs:
5
8
  - id: control id.
6
9
  - value: submitted time string.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formbox/htmx",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Server-rendered HTMX HTML renderer for Formbox FHIR Questionnaires",
5
5
  "private": false,
6
6
  "type": "module",
@@ -40,13 +40,13 @@
40
40
  "vite": "^7.3.1",
41
41
  "vite-plugin-dts": "^4.5.4",
42
42
  "vitest": "^4.0.17",
43
- "@formbox/renderer": "0.4.1",
44
- "@formbox/theme": "0.4.1"
43
+ "@formbox/theme": "0.4.1",
44
+ "@formbox/renderer": "0.4.1"
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",