@formbox/htmx 0.4.3 → 0.5.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/dist/index.js CHANGED
@@ -1,18 +1,43 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
- import { createContext, useContext, useMemo, useCallback, useState, createElement, Children } from "react";
4
+ import { jsx, jsxs, Fragment } from "preact/jsx-runtime";
5
+ import { createContext, useContext, useMemo, useCallback, useState, createElement, Children } from "preact/compat";
6
6
  import bundledStrings from "@formbox/strings";
7
7
  import { computed, action, makeObservable, observable, runInAction, override, reaction, comparer, when } from "mobx";
8
- import { CustomItemExtensionsProvider, useStrings, CustomQuestionnaireExtensionsProvider, StringsContext } from "@formbox/theme";
9
- import { observer } from "mobx-react-lite";
10
8
  import { fromPromise } from "mobx-utils";
11
9
  import { R4AttachmentAdapter, R4QuestionnaireItemAdapter, R4QuestionnaireResponseAdapter, R5AttachmentAdapter, R5QuestionnaireItemAdapter, R5QuestionnaireResponseAdapter } from "@formbox/fhir";
12
10
  import { readdir, readFile } from "node:fs/promises";
13
11
  import path from "node:path";
14
12
  import Handlebars from "handlebars";
15
- import { renderToStaticMarkup } from "react-dom/server.node";
13
+ import { renderToStaticMarkup } from "preact-render-to-string";
14
+ const StringsContext = createContext(
15
+ void 0
16
+ );
17
+ function useStrings() {
18
+ const strings2 = useContext(StringsContext);
19
+ if (strings2 == void 0) {
20
+ throw new Error("StringsContext.Provider is required");
21
+ }
22
+ return strings2;
23
+ }
24
+ const CustomQuestionnaireExtensionsContext = createContext(void 0);
25
+ const CustomItemExtensionsContext = createContext(void 0);
26
+ function CustomQuestionnaireExtensionsProvider({
27
+ value,
28
+ children
29
+ }) {
30
+ return /* @__PURE__ */ jsx(CustomQuestionnaireExtensionsContext.Provider, { value, children });
31
+ }
32
+ function CustomItemExtensionsProvider({
33
+ value,
34
+ children
35
+ }) {
36
+ return /* @__PURE__ */ jsx(CustomItemExtensionsContext.Provider, { value, children });
37
+ }
38
+ function observer(component) {
39
+ return component;
40
+ }
16
41
  const ITEM_CONTROLS = [
17
42
  // display
18
43
  "inline",
@@ -35921,6 +35946,7 @@ const Form$1 = observer(function Form2({
35921
35946
  const languageSelector = store.availableLanguages.length > 1 && store.language && onLanguageChange ? /* @__PURE__ */ jsx(
35922
35947
  ThemedLanguageSelector,
35923
35948
  {
35949
+ id: buildId(store.token, "language"),
35924
35950
  value: store.language,
35925
35951
  onChange: (value) => onLanguageChange(value),
35926
35952
  options: store.availableLanguages.map((language) => ({
@@ -35944,6 +35970,7 @@ const Form$1 = observer(function Form2({
35944
35970
  return /* @__PURE__ */ jsx(
35945
35971
  ThemedForm,
35946
35972
  {
35973
+ id: store.token,
35947
35974
  title: store.title,
35948
35975
  description: store.description,
35949
35976
  languageSelector,
@@ -36550,9 +36577,9 @@ function DateTimeDisplay({ value }) {
36550
36577
  function TimeDisplay({ value }) {
36551
36578
  return /* @__PURE__ */ jsx(Fragment, { children: value });
36552
36579
  }
36553
- function UrlDisplay({ value }) {
36580
+ function UrlDisplay({ id: id2, value }) {
36554
36581
  const { Link: Link2 } = useTheme();
36555
- return /* @__PURE__ */ jsx(Link2, { href: value, target: "_blank", rel: "noreferrer", children: value });
36582
+ return /* @__PURE__ */ jsx(Link2, { id: id2, href: value, target: "_blank", rel: "noreferrer", children: value });
36556
36583
  }
36557
36584
  function ReferenceDisplay({
36558
36585
  value
@@ -36597,6 +36624,7 @@ const VALUE_DISPLAY_BY_TYPE = {
36597
36624
  attachment: AttachmentDisplay
36598
36625
  };
36599
36626
  function ValueDisplay({
36627
+ id: id2,
36600
36628
  type,
36601
36629
  value
36602
36630
  }) {
@@ -36605,7 +36633,7 @@ function ValueDisplay({
36605
36633
  return strings2.value.unanswered;
36606
36634
  } else {
36607
36635
  const Component = VALUE_DISPLAY_BY_TYPE[type];
36608
- return /* @__PURE__ */ jsx(Component, { value });
36636
+ return /* @__PURE__ */ jsx(Component, { id: id2, value });
36609
36637
  }
36610
36638
  }
36611
36639
  const LEGACY_UNIT_TOKEN_PREFIX = "__legacy_unit__";
@@ -36647,12 +36675,20 @@ const QuantityUnitInput = observer(function QuantityUnitInput2({
36647
36675
  token: entry.token,
36648
36676
  disabled: entry.token.startsWith(LEGACY_UNIT_TOKEN_PREFIX),
36649
36677
  exclusive: false,
36650
- label: /* @__PURE__ */ jsx(OptionDisplay2, { children: /* @__PURE__ */ jsx(ValueDisplay, { type: "coding", value: entry.coding }) })
36678
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { children: /* @__PURE__ */ jsx(
36679
+ ValueDisplay,
36680
+ {
36681
+ id: buildId(id2, "option", entry.token, "display"),
36682
+ type: "coding",
36683
+ value: entry.coding
36684
+ }
36685
+ ) })
36651
36686
  }));
36652
- }, [OptionDisplay2, unitSelection.entries]);
36687
+ }, [OptionDisplay2, id2, unitSelection.entries]);
36653
36688
  const customForm = isCustomFormActive && /* @__PURE__ */ jsx(
36654
36689
  CustomForm,
36655
36690
  {
36691
+ id: buildId(id2, "custom-form"),
36656
36692
  content: answer.question.unitOption.effectiveUnitOpen === "optionsOrType" ? /* @__PURE__ */ jsx(
36657
36693
  CodingInput,
36658
36694
  {
@@ -37129,6 +37165,7 @@ const SingleDropdownSelectControl = observer(
37129
37165
  const customOptionForm = isCustomActive && store.customOptionFormState ? /* @__PURE__ */ jsx(
37130
37166
  CustomOptionForm2,
37131
37167
  {
37168
+ id: buildId(id2, "custom-form"),
37132
37169
  content: /* @__PURE__ */ jsx(
37133
37170
  Control,
37134
37171
  {
@@ -37148,11 +37185,18 @@ const SingleDropdownSelectControl = observer(
37148
37185
  const options = useMemo(() => {
37149
37186
  return store.filteredOptions.map((entry) => ({
37150
37187
  token: entry.token,
37151
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: entry.answerType, value: entry.value }) }),
37188
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(
37189
+ ValueDisplay,
37190
+ {
37191
+ id: buildId(id2, "option", entry.token, "display"),
37192
+ type: entry.answerType,
37193
+ value: entry.value
37194
+ }
37195
+ ) }),
37152
37196
  disabled: entry.disabled,
37153
37197
  exclusive: entry.exclusive === true
37154
37198
  }));
37155
- }, [OptionDisplay2, store.filteredOptions]);
37199
+ }, [OptionDisplay2, id2, store.filteredOptions]);
37156
37200
  const specifyOtherOption = store.allowCustom ? {
37157
37201
  token: store.specifyOtherToken,
37158
37202
  label: node.openLabel ?? strings2.selection.specifyOther,
@@ -37170,7 +37214,14 @@ const SingleDropdownSelectControl = observer(
37170
37214
  token: selection.token,
37171
37215
  disabled: selection.disabled,
37172
37216
  exclusive: selection.exclusive === true,
37173
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: selection.answerType, value: selection.value }) })
37217
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(
37218
+ ValueDisplay,
37219
+ {
37220
+ id: buildId(id2, "selected", selection.token, "display"),
37221
+ type: selection.answerType,
37222
+ value: selection.value
37223
+ }
37224
+ ) })
37174
37225
  };
37175
37226
  })();
37176
37227
  return /* @__PURE__ */ jsx(
@@ -37204,7 +37255,19 @@ const MultiDropdownSelectControl = observer(
37204
37255
  const CustomControl = getValueControl(store.customType);
37205
37256
  const selectedOptions = store.selectedOptions.map((selection) => ({
37206
37257
  token: selection.token,
37207
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: selection.answerType, value: selection.value }) }),
37258
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(
37259
+ ValueDisplay,
37260
+ {
37261
+ id: buildId(
37262
+ selection.answer.token,
37263
+ "selected",
37264
+ selection.token,
37265
+ "display"
37266
+ ),
37267
+ type: selection.answerType,
37268
+ value: selection.value
37269
+ }
37270
+ ) }),
37208
37271
  ariaDescribedBy: getIssueErrorId(selection.answer),
37209
37272
  errors: renderErrors(selection.answer),
37210
37273
  disabled: selection.disabled,
@@ -37214,6 +37277,7 @@ const MultiDropdownSelectControl = observer(
37214
37277
  const customOptionForm = formState ? /* @__PURE__ */ jsx(
37215
37278
  CustomOptionForm2,
37216
37279
  {
37280
+ id: buildId(formState.answer.token, "custom-form"),
37217
37281
  content: /* @__PURE__ */ jsx(
37218
37282
  CustomControl,
37219
37283
  {
@@ -37235,9 +37299,22 @@ const MultiDropdownSelectControl = observer(
37235
37299
  token: entry.token,
37236
37300
  disabled: entry.disabled,
37237
37301
  exclusive: entry.exclusive === true,
37238
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: entry.answerType, value: entry.value }) })
37302
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(
37303
+ ValueDisplay,
37304
+ {
37305
+ id: buildId(
37306
+ node.token,
37307
+ "multi-select",
37308
+ "option",
37309
+ entry.token,
37310
+ "display"
37311
+ ),
37312
+ type: entry.answerType,
37313
+ value: entry.value
37314
+ }
37315
+ ) })
37239
37316
  }));
37240
- }, [OptionDisplay2, store.filteredOptions]);
37317
+ }, [OptionDisplay2, node.token, store.filteredOptions]);
37241
37318
  const specifyOtherOption = store.allowCustom ? {
37242
37319
  token: store.specifyOtherToken,
37243
37320
  label: node.openLabel ?? strings2.selection.specifyOther,
@@ -37276,7 +37353,19 @@ const MultiListSelectControl = observer(function MultiListSelectControl2({ node
37276
37353
  const CustomControl = getValueControl(store.customType);
37277
37354
  const selectedOptions = store.selectedOptions.map((selection) => ({
37278
37355
  token: selection.token,
37279
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: selection.answerType, value: selection.value }) }),
37356
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(
37357
+ ValueDisplay,
37358
+ {
37359
+ id: buildId(
37360
+ selection.answer.token,
37361
+ "selected",
37362
+ selection.token,
37363
+ "display"
37364
+ ),
37365
+ type: selection.answerType,
37366
+ value: selection.value
37367
+ }
37368
+ ) }),
37280
37369
  ariaDescribedBy: getIssueErrorId(selection.answer),
37281
37370
  errors: renderErrors(selection.answer),
37282
37371
  disabled: selection.disabled,
@@ -37289,6 +37378,7 @@ const MultiListSelectControl = observer(function MultiListSelectControl2({ node
37289
37378
  const customOptionForm = formState ? /* @__PURE__ */ jsx(
37290
37379
  CustomOptionForm2,
37291
37380
  {
37381
+ id: buildId(formState.answer.token, "custom-form"),
37292
37382
  content: /* @__PURE__ */ jsx(
37293
37383
  CustomControl,
37294
37384
  {
@@ -37310,9 +37400,22 @@ const MultiListSelectControl = observer(function MultiListSelectControl2({ node
37310
37400
  token: entry.token,
37311
37401
  disabled: entry.disabled,
37312
37402
  exclusive: entry.exclusive === true,
37313
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: entry.answerType, value: entry.value }) })
37403
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(
37404
+ ValueDisplay,
37405
+ {
37406
+ id: buildId(
37407
+ node.token,
37408
+ "multi-select",
37409
+ "option",
37410
+ entry.token,
37411
+ "display"
37412
+ ),
37413
+ type: entry.answerType,
37414
+ value: entry.value
37415
+ }
37416
+ ) })
37314
37417
  }));
37315
- }, [OptionDisplay2, store.filteredOptions]);
37418
+ }, [OptionDisplay2, node.token, store.filteredOptions]);
37316
37419
  const specifyOtherOption = store.allowCustom ? {
37317
37420
  token: store.specifyOtherToken,
37318
37421
  label: node.openLabel ?? strings2.selection.specifyOther,
@@ -37356,6 +37459,7 @@ const SingleListSelectControl = observer(
37356
37459
  const customOptionForm = isCustomActive && store.customOptionFormState ? /* @__PURE__ */ jsx(
37357
37460
  CustomOptionForm2,
37358
37461
  {
37462
+ id: buildId(id2, "custom-form"),
37359
37463
  content: /* @__PURE__ */ jsx(
37360
37464
  Control,
37361
37465
  {
@@ -37375,11 +37479,18 @@ const SingleListSelectControl = observer(
37375
37479
  const options = useMemo(() => {
37376
37480
  return store.filteredOptions.map((entry) => ({
37377
37481
  token: entry.token,
37378
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: entry.answerType, value: entry.value }) }),
37482
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: entry.prefix, media: entry.media, children: /* @__PURE__ */ jsx(
37483
+ ValueDisplay,
37484
+ {
37485
+ id: buildId(id2, "option", entry.token, "display"),
37486
+ type: entry.answerType,
37487
+ value: entry.value
37488
+ }
37489
+ ) }),
37379
37490
  disabled: entry.disabled,
37380
37491
  exclusive: entry.exclusive === true
37381
37492
  }));
37382
- }, [OptionDisplay2, store.filteredOptions]);
37493
+ }, [OptionDisplay2, id2, store.filteredOptions]);
37383
37494
  const specifyOtherOption = store.allowCustom ? {
37384
37495
  token: store.specifyOtherToken,
37385
37496
  label: node.openLabel ?? strings2.selection.specifyOther,
@@ -37397,7 +37508,14 @@ const SingleListSelectControl = observer(
37397
37508
  token: selection.token,
37398
37509
  disabled: selection.disabled,
37399
37510
  exclusive: selection.exclusive === true,
37400
- label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: selection.answerType, value: selection.value }) })
37511
+ label: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: selection.prefix, media: selection.media, children: /* @__PURE__ */ jsx(
37512
+ ValueDisplay,
37513
+ {
37514
+ id: buildId(id2, "selected", selection.token, "display"),
37515
+ type: selection.answerType,
37516
+ value: selection.value
37517
+ }
37518
+ ) })
37401
37519
  };
37402
37520
  })();
37403
37521
  return /* @__PURE__ */ jsx(
@@ -37875,7 +37993,14 @@ const SelectionTableControl = observer(function SelectionTableControl2({
37875
37993
  })),
37876
37994
  rows: node.table.optionAxis.map((option) => ({
37877
37995
  token: option.token,
37878
- content: /* @__PURE__ */ jsx(Label2, { id: buildId(node.token, option.token), isExpanded: true, children: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: option.prefix, media: option.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: option.answerType, value: option.value }) }) }),
37996
+ content: /* @__PURE__ */ jsx(Label2, { id: buildId(node.token, option.token), isExpanded: true, children: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: option.prefix, media: option.media, children: /* @__PURE__ */ jsx(
37997
+ ValueDisplay,
37998
+ {
37999
+ id: buildId(node.token, option.token, "display"),
38000
+ type: option.answerType,
38001
+ value: option.value
38002
+ }
38003
+ ) }) }),
37879
38004
  cells: node.table.questions.map((question) => ({
37880
38005
  token: buildId(question.token, option.token),
37881
38006
  content: /* @__PURE__ */ jsx(
@@ -37895,7 +38020,14 @@ const SelectionTableControl = observer(function SelectionTableControl2({
37895
38020
  {
37896
38021
  columns: node.table.optionAxis.map((option) => ({
37897
38022
  token: option.token,
37898
- content: /* @__PURE__ */ jsx(Label2, { id: buildId(node.token, option.token), isExpanded: true, children: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: option.prefix, media: option.media, children: /* @__PURE__ */ jsx(ValueDisplay, { type: option.answerType, value: option.value }) }) })
38023
+ content: /* @__PURE__ */ jsx(Label2, { id: buildId(node.token, option.token), isExpanded: true, children: /* @__PURE__ */ jsx(OptionDisplay2, { prefix: option.prefix, media: option.media, children: /* @__PURE__ */ jsx(
38024
+ ValueDisplay,
38025
+ {
38026
+ id: buildId(node.token, option.token, "display"),
38027
+ type: option.answerType,
38028
+ value: option.value
38029
+ }
38030
+ ) }) })
37899
38031
  })),
37900
38032
  rows: node.table.questions.map((question) => ({
37901
38033
  token: question.token,
@@ -59512,6 +59644,24 @@ function signatureName(path2) {
59512
59644
  function actionValue(kind, path2) {
59513
59645
  return `${kind}${pathParts(path2).map((part) => `[${part}]`).join("")}`;
59514
59646
  }
59647
+ function stableId(base, ...parts) {
59648
+ if (base === void 0) {
59649
+ return void 0;
59650
+ }
59651
+ return [base, ...parts].filter((part) => part !== void 0).map(String).join("__");
59652
+ }
59653
+ function pathControlId(token, path2, ...parts) {
59654
+ if (path2 === void 0) {
59655
+ return void 0;
59656
+ }
59657
+ return stableId(
59658
+ token,
59659
+ ...path2.flatMap(
59660
+ (segment) => segment.index === void 0 ? [segment.linkId] : [segment.linkId, segment.index]
59661
+ ),
59662
+ ...parts
59663
+ );
59664
+ }
59515
59665
  function lastLinkId(path2) {
59516
59666
  return path2.at(-1)?.linkId ?? "";
59517
59667
  }
@@ -59536,7 +59686,7 @@ function isDefined(value) {
59536
59686
  function isPreservedOptionToken$1(token) {
59537
59687
  return token.includes("__custom__") || token.includes("__legacy__");
59538
59688
  }
59539
- function mediaHtml(attachment, fallbackLabel) {
59689
+ function mediaHtml(attachment, fallbackLabel, id2) {
59540
59690
  if (attachment === void 0) {
59541
59691
  return "";
59542
59692
  }
@@ -59550,12 +59700,12 @@ function mediaHtml(attachment, fallbackLabel) {
59550
59700
  return `<img${attribute("src", source)}${attribute("alt", label)}>`;
59551
59701
  }
59552
59702
  if (contentType?.startsWith("audio/")) {
59553
- return `<audio controls${attribute("src", source)}></audio>`;
59703
+ return `<audio controls${attribute("id", id2)}${attribute("src", source)}></audio>`;
59554
59704
  }
59555
59705
  if (contentType?.startsWith("video/")) {
59556
- return `<video controls${attribute("src", source)}></video>`;
59706
+ return `<video controls${attribute("id", id2)}${attribute("src", source)}></video>`;
59557
59707
  }
59558
- return `<a${attribute("href", source)} target="_blank" rel="noreferrer">${escapeHtml$1(label)}</a>`;
59708
+ return `<a${attribute("id", id2)}${attribute("href", source)} target="_blank" rel="noreferrer">${escapeHtml$1(label)}</a>`;
59559
59709
  }
59560
59710
  function formFieldsTemplate(properties) {
59561
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;
@@ -59571,7 +59721,7 @@ function formFieldsTemplate(properties) {
59571
59721
  properties.after ?? "",
59572
59722
  properties.signature ?? "",
59573
59723
  renderPagination(properties),
59574
- `<button type="submit" name="${ACTION_FIELD}" value="submit">${escapeHtml$1(properties.submitLabel)}</button>`
59724
+ `<button type="submit"${attribute("id", stableId(properties.id, "submit"))} name="${ACTION_FIELD}" value="submit">${escapeHtml$1(properties.submitLabel)}</button>`
59575
59725
  ].join("");
59576
59726
  }
59577
59727
  function fieldAttributes$1(path2, field) {
@@ -59682,7 +59832,7 @@ function tableColumn(column, renderHtml) {
59682
59832
  widthStyle: column.width ? `width:${column.width}` : void 0
59683
59833
  };
59684
59834
  }
59685
- function tableRow(row, renderHtml, strings2) {
59835
+ function tableRow(row, renderHtml, strings2, token) {
59686
59836
  const path2 = row.path;
59687
59837
  return {
59688
59838
  token: row.token,
@@ -59694,6 +59844,7 @@ function tableRow(row, renderHtml, strings2) {
59694
59844
  actionName: ACTION_FIELD,
59695
59845
  linkId: path2 ? lastLinkId(path2) : void 0,
59696
59846
  removeAction: row.onRemove !== void 0 && row.canRemove === true && path2 ? actionValue("remove-group", path2) : void 0,
59847
+ removeId: pathControlId(token, path2, "remove-group"),
59697
59848
  removeLabel: strings2.group.removeSection,
59698
59849
  removeLabelHtml: escapeHtml$1(strings2.group.removeSection)
59699
59850
  };
@@ -59717,9 +59868,9 @@ function renderPagination(properties) {
59717
59868
  }
59718
59869
  return [
59719
59870
  "<nav>",
59720
- pagination.disabledPrev ? "" : `<button type="submit" name="${ACTION_FIELD}" value="page-prev">${escapeHtml$1(pagination.previousLabel)}</button>`,
59871
+ pagination.disabledPrev ? "" : `<button type="submit"${attribute("id", pagination.previousId)} name="${ACTION_FIELD}" value="page-prev">${escapeHtml$1(pagination.previousLabel)}</button>`,
59721
59872
  `<span>${String(pagination.current)} / ${String(pagination.total)}</span>`,
59722
- pagination.disabledNext ? "" : `<button type="submit" name="${ACTION_FIELD}" value="page-next">${escapeHtml$1(pagination.nextLabel)}</button>`,
59873
+ pagination.disabledNext ? "" : `<button type="submit"${attribute("id", pagination.nextId)} name="${ACTION_FIELD}" value="page-next">${escapeHtml$1(pagination.nextLabel)}</button>`,
59723
59874
  "</nav>"
59724
59875
  ].join("");
59725
59876
  }
@@ -61163,7 +61314,7 @@ function stripHtmlTag(ssr) {
61163
61314
  return ssr.replaceAll(/<x-html\b[^>]*>/gu, "").replaceAll("</x-html>", "");
61164
61315
  }
61165
61316
  function AnswerList(properties) {
61166
- const { templates } = useHtmxTheme();
61317
+ const { templates, token } = useHtmxTheme();
61167
61318
  const renderHtml = useHtml();
61168
61319
  const strings2 = useStrings();
61169
61320
  const children = Children.toArray(properties.children);
@@ -61173,6 +61324,7 @@ function AnswerList(properties) {
61173
61324
  children: renderHtml(properties.children),
61174
61325
  actionName: ACTION_FIELD,
61175
61326
  addAction: properties.onAdd !== void 0 && properties.canAdd && path2 ? actionValue("add-answer", path2) : void 0,
61327
+ addId: pathControlId(token, path2, "add-answer"),
61176
61328
  addLabel: strings2.selection.addAnother,
61177
61329
  count: path2 ? children.length : void 0,
61178
61330
  countName: path2 ? countName(path2) : void 0,
@@ -61181,7 +61333,7 @@ function AnswerList(properties) {
61181
61333
  });
61182
61334
  }
61183
61335
  function AnswerScaffold(properties) {
61184
- const { templates } = useHtmxTheme();
61336
+ const { templates, token } = useHtmxTheme();
61185
61337
  const renderHtml = useHtml();
61186
61338
  const strings2 = useStrings();
61187
61339
  const path2 = properties.path;
@@ -61193,6 +61345,7 @@ function AnswerScaffold(properties) {
61193
61345
  actionName: ACTION_FIELD,
61194
61346
  linkId: path2 ? lastLinkId(path2) : void 0,
61195
61347
  removeAction: properties.onRemove !== void 0 && properties.canRemove && path2 ? actionValue("remove-answer", path2) : void 0,
61348
+ removeId: pathControlId(token, path2, "remove-answer"),
61196
61349
  removeLabel: strings2.group.removeSection
61197
61350
  });
61198
61351
  }
@@ -61262,6 +61415,7 @@ function CheckboxList(properties) {
61262
61415
  orientation: properties.orientation,
61263
61416
  options: options.map((option) => ({
61264
61417
  ...option,
61418
+ id: stableId(properties.id, "option", option.token) ?? option.token,
61265
61419
  selected: selectedTokens.has(option.token),
61266
61420
  disabled: Boolean(properties.disabled) || option.disabled,
61267
61421
  hiddenInput: name && preservedByToken.has(option.token) ? { name, value: option.token } : void 0
@@ -61281,15 +61435,19 @@ function CheckboxList(properties) {
61281
61435
  });
61282
61436
  }
61283
61437
  function CustomOptionForm(properties) {
61284
- const { templates } = useHtmxTheme();
61438
+ const { templates, token } = useHtmxTheme();
61285
61439
  const renderHtml = useHtml();
61286
61440
  const strings2 = useStrings();
61441
+ const id2 = properties.id ?? stableId(token, "custom-option-form");
61287
61442
  return renderTemplate(templates.CustomOptionForm, {
61443
+ id: id2,
61288
61444
  canSubmit: properties.canSubmit,
61289
61445
  actionName: ACTION_FIELD,
61290
61446
  cancelLabel: strings2.dialog.cancel,
61447
+ cancelId: stableId(id2, "cancel"),
61291
61448
  content: renderHtml(properties.content),
61292
61449
  errors: renderHtml(properties.errors),
61450
+ submitId: stableId(id2, "submit"),
61293
61451
  submitLabel: strings2.dialog.submit
61294
61452
  });
61295
61453
  }
@@ -61370,6 +61528,7 @@ function FileInput(properties) {
61370
61528
  disabled: properties.disabled,
61371
61529
  accept: properties.accept,
61372
61530
  clearLabel: strings2.file.clearAction,
61531
+ clearId: stableId(properties.id, "clear"),
61373
61532
  hiddenValue: properties.value && attributes.name ? JSON.stringify(properties.value) : void 0,
61374
61533
  clearAction: properties.value !== void 0 && attributes.name !== void 0 && !properties.disabled,
61375
61534
  dataLinkId: attributes["data-fb-link-id"],
@@ -61383,6 +61542,7 @@ function Flyover(properties) {
61383
61542
  const strings2 = useStrings();
61384
61543
  return renderTemplate(templates.Flyover, {
61385
61544
  id: properties.id,
61545
+ buttonId: stableId(properties.id, "button"),
61386
61546
  ariaLabel: strings2.aria.flyover,
61387
61547
  children: renderHtml(properties.children)
61388
61548
  });
@@ -61396,18 +61556,22 @@ function Footer(properties) {
61396
61556
  });
61397
61557
  }
61398
61558
  function Form(properties) {
61399
- const { action: action2, hiddenFields, templates } = useHtmxTheme();
61559
+ const { action: action2, hiddenFields, templates, token } = useHtmxTheme();
61400
61560
  const renderHtml = useHtml();
61401
61561
  const strings2 = useStrings();
61562
+ const id2 = properties.id ?? token;
61402
61563
  const pagination = properties.pagination ? {
61403
61564
  current: properties.pagination.current,
61404
61565
  total: properties.pagination.total,
61405
61566
  disabledPrev: properties.pagination.disabledPrev,
61406
61567
  disabledNext: properties.pagination.disabledNext,
61568
+ nextId: stableId(id2, "pagination", "next"),
61407
61569
  nextLabel: strings2.pagination.next,
61570
+ previousId: stableId(id2, "pagination", "previous"),
61408
61571
  previousLabel: strings2.pagination.previous
61409
61572
  } : void 0;
61410
61573
  const formProperties = {
61574
+ id: id2,
61411
61575
  title: properties.title,
61412
61576
  description: properties.description,
61413
61577
  customExtensions: properties.customExtensions,
@@ -61423,12 +61587,12 @@ function Form(properties) {
61423
61587
  const fields = [hiddenFields, formFieldsTemplate(formProperties)].join("");
61424
61588
  return renderTemplate(templates.Form, {
61425
61589
  ...formProperties,
61426
- attributes: defaultAttributes(action2),
61590
+ attributes: { id: id2, ...defaultAttributes(action2) },
61427
61591
  fields
61428
61592
  });
61429
61593
  }
61430
61594
  function GroupList(properties) {
61431
- const { templates } = useHtmxTheme();
61595
+ const { templates, token } = useHtmxTheme();
61432
61596
  const renderHtml = useHtml();
61433
61597
  const strings2 = useStrings();
61434
61598
  const groups2 = Children.toArray(properties.children);
@@ -61443,6 +61607,7 @@ function GroupList(properties) {
61443
61607
  children: renderHtml(properties.children),
61444
61608
  actionName: ACTION_FIELD,
61445
61609
  addAction: properties.onAdd !== void 0 && properties.canAdd && path2 ? actionValue("add-group", path2) : void 0,
61610
+ addId: pathControlId(token, path2, "add-group"),
61446
61611
  addLabel: strings2.group.addSection,
61447
61612
  count: path2 ? count : void 0,
61448
61613
  countName: path2 ? countName(path2) : void 0,
@@ -61450,7 +61615,7 @@ function GroupList(properties) {
61450
61615
  });
61451
61616
  }
61452
61617
  function GroupScaffold(properties) {
61453
- const { templates } = useHtmxTheme();
61618
+ const { templates, token } = useHtmxTheme();
61454
61619
  const renderHtml = useHtml();
61455
61620
  const strings2 = useStrings();
61456
61621
  const path2 = properties.path;
@@ -61473,8 +61638,10 @@ function GroupScaffold(properties) {
61473
61638
  expandedValue: expandedName$1 ? String(Boolean(properties.isExpanded)) : void 0,
61474
61639
  expandLabel: strings2.collapsible.expand,
61475
61640
  removeAction: properties.onRemove !== void 0 && properties.canRemove && path2 ? actionValue("remove-group", path2) : void 0,
61641
+ removeId: pathControlId(token, path2, "remove-group"),
61476
61642
  removeLabel: strings2.group.removeSection,
61477
61643
  toggleAction,
61644
+ toggleId: pathControlId(token, path2, "toggle-expanded"),
61478
61645
  summaryLabel: properties.isExpanded ? strings2.collapsible.collapse : strings2.collapsible.expand,
61479
61646
  expandedChildren: properties.isExpanded ? renderHtml(properties.children) : ""
61480
61647
  });
@@ -61493,6 +61660,7 @@ function Help(properties) {
61493
61660
  const strings2 = useStrings();
61494
61661
  return renderTemplate(templates.Help, {
61495
61662
  id: properties.id,
61663
+ buttonId: stableId(properties.id, "button"),
61496
61664
  ariaLabel: strings2.aria.help,
61497
61665
  children: renderHtml(properties.children)
61498
61666
  });
@@ -61545,18 +61713,26 @@ function Label(properties) {
61545
61713
  help: renderHtml(properties.help),
61546
61714
  legal: renderHtml(properties.legal),
61547
61715
  flyover: renderHtml(properties.flyover),
61548
- media: mediaHtml(properties.media, strings2.inputs.attachmentLabel),
61716
+ media: mediaHtml(
61717
+ properties.media,
61718
+ strings2.inputs.attachmentLabel,
61719
+ stableId(properties.id, "media")
61720
+ ),
61549
61721
  ...properties.supportHyperlinks ? {
61550
- supportHyperlinks: properties.supportHyperlinks.map((link) => ({
61551
- ...link,
61552
- labelHtml: escapeHtml$1(link.label || link.href)
61553
- }))
61722
+ supportHyperlinks: properties.supportHyperlinks.map(
61723
+ (link, index) => ({
61724
+ ...link,
61725
+ id: stableId(properties.id, "support", index) ?? String(index),
61726
+ labelHtml: escapeHtml$1(link.label || link.href)
61727
+ })
61728
+ )
61554
61729
  } : {}
61555
61730
  });
61556
61731
  }
61557
61732
  function LanguageSelector(properties) {
61558
- const { templates } = useHtmxTheme();
61733
+ const { templates, token } = useHtmxTheme();
61559
61734
  return renderTemplate(templates.LanguageSelector, {
61735
+ id: properties.id ?? stableId(token, "language"),
61560
61736
  value: properties.value,
61561
61737
  name: LANGUAGE_FIELD,
61562
61738
  options: properties.options.map((option) => ({
@@ -61571,6 +61747,7 @@ function Legal(properties) {
61571
61747
  const strings2 = useStrings();
61572
61748
  return renderTemplate(templates.Legal, {
61573
61749
  id: properties.id,
61750
+ buttonId: stableId(properties.id, "button"),
61574
61751
  ariaLabel: strings2.aria.legal,
61575
61752
  children: renderHtml(properties.children)
61576
61753
  });
@@ -61579,6 +61756,7 @@ function Link(properties) {
61579
61756
  const { templates } = useHtmxTheme();
61580
61757
  const renderHtml = useHtml();
61581
61758
  return renderTemplate(templates.Link, {
61759
+ id: properties.id,
61582
61760
  href: properties.href,
61583
61761
  target: properties.target,
61584
61762
  rel: properties.rel,
@@ -61637,6 +61815,7 @@ function MultiSelectInput(properties) {
61637
61815
  baselineName,
61638
61816
  options: options.map((option) => ({
61639
61817
  ...option,
61818
+ id: stableId(properties.id, "option", option.token) ?? option.token,
61640
61819
  selected: selectedTokens.has(option.token),
61641
61820
  disabled: Boolean(properties.disabled) || option.disabled,
61642
61821
  hiddenInput: name && preservedByToken.has(option.token) ? { name, value: option.token } : void 0
@@ -61682,7 +61861,7 @@ function OptionsLoading(properties) {
61682
61861
  });
61683
61862
  }
61684
61863
  function QuestionScaffold(properties) {
61685
- const { templates } = useHtmxTheme();
61864
+ const { templates, token } = useHtmxTheme();
61686
61865
  const renderHtml = useHtml();
61687
61866
  const strings2 = useStrings();
61688
61867
  const path2 = properties.path;
@@ -61704,6 +61883,7 @@ function QuestionScaffold(properties) {
61704
61883
  expandedValue: expandedName$1 ? String(Boolean(properties.isExpanded)) : void 0,
61705
61884
  expandLabel: strings2.collapsible.expand,
61706
61885
  toggleAction,
61886
+ toggleId: pathControlId(token, path2, "toggle-expanded"),
61707
61887
  summaryLabel: properties.isExpanded ? strings2.collapsible.collapse : strings2.collapsible.expand,
61708
61888
  expandedChildren: properties.isExpanded ? renderHtml(properties.children) : ""
61709
61889
  });
@@ -61757,6 +61937,7 @@ function RadioButtonList(properties) {
61757
61937
  hiddenValue: (preserveValue || mirrorValue) && selectedToken && attributes.name ? selectedToken : void 0,
61758
61938
  options: options.map((option) => ({
61759
61939
  ...option,
61940
+ id: stableId(properties.id, "option", option.token) ?? option.token,
61760
61941
  checked: option.token === selectedToken,
61761
61942
  disabled: Boolean(properties.disabled) || Boolean(option.disabled)
61762
61943
  })),
@@ -61878,10 +62059,12 @@ function TabContainer(properties) {
61878
62059
  });
61879
62060
  }
61880
62061
  function Table(properties) {
61881
- const { templates } = useHtmxTheme();
62062
+ const { templates, token } = useHtmxTheme();
61882
62063
  const renderHtml = useHtml();
61883
62064
  const strings2 = useStrings();
61884
- const rows = properties.rows.map((row) => tableRow(row, renderHtml, strings2));
62065
+ const rows = properties.rows.map(
62066
+ (row) => tableRow(row, renderHtml, strings2, token)
62067
+ );
61885
62068
  return renderTemplate(templates.Table, {
61886
62069
  columns: properties.columns.map(
61887
62070
  (column) => tableColumn(column, renderHtml)
@@ -61993,6 +62176,7 @@ function renderStoreFields(store, templates, action2) {
61993
62176
  const theme2 = createTheme();
61994
62177
  const htmxTheme = {
61995
62178
  templates,
62179
+ token: store.token,
61996
62180
  hiddenFields: renderHiddenFieldsForStore(store),
61997
62181
  activeTabValue: activeTab,
61998
62182
  action: action2