@rachelallyson/hero-hook-form 2.14.0 → 2.15.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/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.15.0] - 2026-02-02
6
+
7
+ ### Added
8
+
9
+ - **ConfigProvider: autocomplete defaults** – `HeroHookFormDefaultsConfig` and `useHeroHookFormDefaults()` support `defaults.autocomplete`. `AutocompleteField` spreads these defaults so Autocomplete respects the same global styling (color, size, variant, radius, labelPlacement) as Input, Textarea, and Select when using `HeroHookFormProvider`.
10
+ - **createFieldArrayCustomConfig: readOnly** – New `readOnly?: boolean` option. When true, the add button (and empty-state add block) is not rendered. `readOnly` is passed into each item’s props so custom `renderItem` / `getItemFieldConfig` can hide remove/reorder controls. Use instead of `renderAddButton: () => null` for display-only arrays.
11
+
12
+ ### Fixed
13
+
14
+ - **ServerActionForm autocomplete options** – `AutocompleteItem` for autocomplete fields now receives `textValue={item.label ?? String(item.value)}` so options have a stable plain-text value for accessibility, type-to-select, and Cypress/automation even when using custom `renderItem`.
15
+
16
+ ### Changed
17
+
18
+ - **AutocompleteField** – Uses `useHeroHookFormDefaults()` and spreads `defaults.autocomplete` so the control picks up provider styling (e.g. `HeroHookFormProvider` with `defaults.common` or `defaults.autocomplete`).
19
+ - **Example: Custom Field Array Demo** – Uses `readOnly: true` instead of `renderAddButton: () => null`. E2E test added to assert “Add Item” is not shown when readOnly is true.
20
+
5
21
  ## [2.14.0] - 2026-01-29
6
22
 
7
23
  ### Added
package/dist/index.d.ts CHANGED
@@ -4237,6 +4237,8 @@ interface FieldArrayItemRenderProps<TFieldValues extends FieldValues, TArrayPath
4237
4237
  onMoveUp: () => void;
4238
4238
  onMoveDown: () => void;
4239
4239
  onRemove: () => void;
4240
+ /** When true, add/remove/reorder are hidden; use to hide your own buttons */
4241
+ readOnly?: boolean;
4240
4242
  }
4241
4243
  /**
4242
4244
  * Options for creating a custom field array config
@@ -4270,6 +4272,8 @@ interface CreateFieldArrayCustomConfigOptions<TFieldValues extends FieldValues>
4270
4272
  max?: number;
4271
4273
  /** Enable reordering of array items */
4272
4274
  enableReordering?: boolean;
4275
+ /** When true, no add button is shown; readOnly is passed to renderItem/getItemFieldConfig so you can hide remove/reorder */
4276
+ readOnly?: boolean;
4273
4277
  /** Optional className */
4274
4278
  className?: string;
4275
4279
  }
package/dist/index.js CHANGED
@@ -231,8 +231,14 @@ function useHeroHookFormDefaults() {
231
231
  size: "md",
232
232
  variant: "bordered"
233
233
  };
234
+ const autocompleteBase = {
235
+ radius: "md",
236
+ size: "md",
237
+ variant: "bordered"
238
+ };
234
239
  return {
235
240
  autocomplete: {
241
+ ...autocompleteBase,
236
242
  ...commonAutocomplete,
237
243
  ...cfg.autocomplete ?? {}
238
244
  },
@@ -486,11 +492,16 @@ function AutocompleteField(props) {
486
492
  { isDisabled, label },
487
493
  { allowsCustomValue }
488
494
  );
495
+ const autocompleteMerged = { ...defaults.autocomplete };
496
+ for (const [key, value] of Object.entries(rest)) {
497
+ if (value !== void 0) {
498
+ autocompleteMerged[key] = value;
499
+ }
500
+ }
489
501
  return /* @__PURE__ */ React2.createElement("div", { className }, /* @__PURE__ */ React2.createElement(
490
502
  Autocomplete,
491
503
  {
492
- ...defaults.autocomplete,
493
- ...rest,
504
+ ...autocompleteMerged,
494
505
  ...defaultItems && {
495
506
  defaultItems
496
507
  },
@@ -3193,7 +3204,14 @@ function ServerActionField({
3193
3204
  onInputChange: setValue,
3194
3205
  items
3195
3206
  },
3196
- items.map((item) => /* @__PURE__ */ React21.createElement(AutocompleteItem, { key: String(item.value) }, typeof stringConfig.renderItem === "function" ? stringConfig.renderItem(item) : item.label))
3207
+ items.map((item) => /* @__PURE__ */ React21.createElement(
3208
+ AutocompleteItem,
3209
+ {
3210
+ key: String(item.value),
3211
+ textValue: item.label ?? String(item.value)
3212
+ },
3213
+ typeof stringConfig.renderItem === "function" ? stringConfig.renderItem(item) : item.label
3214
+ ))
3197
3215
  );
3198
3216
  }
3199
3217
  case "slider": {
@@ -5823,6 +5841,7 @@ function createFieldArrayCustomConfig(options) {
5823
5841
  max = 10,
5824
5842
  min = 0,
5825
5843
  name,
5844
+ readOnly = false,
5826
5845
  renderAddButton,
5827
5846
  renderItem
5828
5847
  } = options;
@@ -5885,7 +5904,8 @@ function createFieldArrayCustomConfig(options) {
5885
5904
  index,
5886
5905
  onMoveDown: () => handleMoveDown(index),
5887
5906
  onMoveUp: () => handleMoveUp(index),
5888
- onRemove: () => handleRemove(index)
5907
+ onRemove: () => handleRemove(index),
5908
+ readOnly
5889
5909
  });
5890
5910
  return /* @__PURE__ */ React27.createElement("div", { className }, /* @__PURE__ */ React27.createElement("div", { className: "space-y-4" }, fields.map((field2, index) => {
5891
5911
  if (getItemFieldConfig) {
@@ -5902,7 +5922,7 @@ function createFieldArrayCustomConfig(options) {
5902
5922
  );
5903
5923
  }
5904
5924
  return /* @__PURE__ */ React27.createElement(React27.Fragment, { key: field2.id }, renderItem(itemProps(index)));
5905
- }), fields.length === 0 && renderAddButton ? /* @__PURE__ */ React27.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React27.createElement("p", null, "No ", label?.toLowerCase() || "items", " added yet."), renderAddButton({ canAdd, onAdd: handleAdd })) : null, fields.length > 0 && renderAddButton ? renderAddButton({ canAdd, onAdd: handleAdd }) : canAdd && /* @__PURE__ */ React27.createElement(
5925
+ }), !readOnly && fields.length === 0 && renderAddButton ? /* @__PURE__ */ React27.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React27.createElement("p", null, "No ", label?.toLowerCase() || "items", " added yet."), renderAddButton({ canAdd, onAdd: handleAdd })) : null, !readOnly && (fields.length > 0 && renderAddButton ? renderAddButton({ canAdd, onAdd: handleAdd }) : canAdd && /* @__PURE__ */ React27.createElement(
5906
5926
  Button6,
5907
5927
  {
5908
5928
  variant: "bordered",
@@ -5910,7 +5930,7 @@ function createFieldArrayCustomConfig(options) {
5910
5930
  className: "w-full"
5911
5931
  },
5912
5932
  "Add Item"
5913
- )));
5933
+ ))));
5914
5934
  },
5915
5935
  type: "custom"
5916
5936
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rachelallyson/hero-hook-form",
3
- "version": "2.14.0",
3
+ "version": "2.15.0",
4
4
  "description": "Typed form helpers that combine React Hook Form and HeroUI components.",
5
5
  "author": "Rachel Higley",
6
6
  "homepage": "https://rachelallyson.github.io/hero-hook-form/",