@rachelallyson/hero-hook-form 2.8.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,41 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.9.1] - 2026-01-28
6
+
7
+ ### Fixed
8
+
9
+ - **Cypress Testing: fillInputByLabel clearing behavior**: Fixed issue where `fillInputByLabel` may not properly clear number inputs with default values
10
+ - Refactored to use a single chain ensuring clear operation completes before typing
11
+ - Ensures reliable clearing of all input types, especially number inputs with default values
12
+ - Clearing is now explicitly documented as the default behavior
13
+
14
+ ## [2.9.0] - 2026-01-22
15
+
16
+ ### Added
17
+
18
+ - **Documentation: Memory-Safe Forms Guide**: Comprehensive guide for preventing Cypress memory leaks
19
+ - Complete migration guide from problematic to memory-safe conditional field arrays
20
+ - Working code examples and best practices
21
+ - Troubleshooting section for memory issues
22
+ - Performance optimization recommendations
23
+
24
+ - **Examples: Question Form Demo**: Working demonstration of memory-safe conditional field arrays
25
+ - Interactive example showing MULTIPLE_CHOICE question types
26
+ - Before/after code comparisons
27
+ - Real-world implementation patterns
28
+ - Cypress e2e test coverage
29
+
30
+ - **Enhanced Testing**: Additional test coverage and refinements
31
+ - Question form e2e tests demonstrating memory safety
32
+ - Updated Cypress test patterns for memory optimization
33
+ - Comprehensive validation of conditional field array behavior
34
+
35
+ ### Fixed
36
+
37
+ - **Test File Naming**: Corrected Cypress test file extensions (`.cy.ts` vs `.spec.ts`)
38
+ - **Conditional Rendering**: Improved formatting and error handling in conditional field components
39
+
5
40
  ## [2.8.0] - 2026-01-22
6
41
 
7
42
  ### Added
@@ -334,7 +334,7 @@ var init_utils = __esm({
334
334
  });
335
335
 
336
336
  // src/cypress/helpers.ts
337
- function fillInputByName(name, value, options = {}) {
337
+ function fillInputByName(name, value, options = { clear: true }) {
338
338
  return withRetry(() => {
339
339
  waitForFormReady();
340
340
  const element = cy.get(`input[name="${name}"], textarea[name="${name}"]`, { timeout: DEFAULT_CONFIG.timeout }).should("exist").should("be.visible");
@@ -347,7 +347,7 @@ function fillInputByName(name, value, options = {}) {
347
347
  });
348
348
  }, DEFAULT_CONFIG);
349
349
  }
350
- function fillInputByType(type, value, index = 0, options = {}) {
350
+ function fillInputByType(type, value, index = 0, options = { clear: true }) {
351
351
  const selector = type === "textarea" ? buildHeroUISelector("textarea") : buildHeroUISelector("input", type);
352
352
  const element = index > 0 ? cy.get(selector).eq(index) : cy.get(selector).first();
353
353
  return withRetry(() => {
@@ -357,7 +357,7 @@ function fillInputByType(type, value, index = 0, options = {}) {
357
357
  return element.type(value, { force: true });
358
358
  }, DEFAULT_CONFIG);
359
359
  }
360
- function fillInputByPlaceholder(placeholder, value, options = {}) {
360
+ function fillInputByPlaceholder(placeholder, value, options = { clear: true }) {
361
361
  const selector = `input[placeholder*="${placeholder}"], textarea[placeholder*="${placeholder}"]`;
362
362
  return withRetry(() => {
363
363
  const element = cy.get(selector);
@@ -367,17 +367,17 @@ function fillInputByPlaceholder(placeholder, value, options = {}) {
367
367
  return element.type(value, { force: true });
368
368
  }, DEFAULT_CONFIG);
369
369
  }
370
- function fillInputByLabel(label, value, options = {}) {
370
+ function fillInputByLabel(label, value, options = { clear: true }) {
371
371
  return withRetry(() => {
372
- return cy.contains("label", label).closest("div").find("input, textarea").first().then(($el) => {
373
- if (options.clear !== false) {
374
- cy.wrap($el).clear({ force: true });
375
- }
376
- return cy.wrap($el).type(value, { force: true });
377
- });
372
+ const element = cy.contains("label", label).closest("div").find("input, textarea").first();
373
+ const shouldClear = options.clear !== false;
374
+ if (shouldClear) {
375
+ element.clear({ force: true });
376
+ }
377
+ return element.type(value, { force: true });
378
378
  }, DEFAULT_CONFIG);
379
379
  }
380
- function fillTextareaByName(name, value, options = {}) {
380
+ function fillTextareaByName(name, value, options = { clear: true }) {
381
381
  return withRetry(() => {
382
382
  const element = cy.get(`textarea[name="${name}"]`);
383
383
  if (options.clear !== false) {
@@ -386,7 +386,7 @@ function fillTextareaByName(name, value, options = {}) {
386
386
  return element.type(value, { force: true });
387
387
  }, DEFAULT_CONFIG);
388
388
  }
389
- function fillTextarea(value, index = 0, options = {}) {
389
+ function fillTextarea(value, index = 0, options = { clear: true }) {
390
390
  const selector = HERO_UI_SELECTORS.textarea;
391
391
  return withRetry(() => {
392
392
  const element = index > 0 ? cy.get(selector).eq(index) : cy.get(selector).first();
package/dist/index.js CHANGED
@@ -400,22 +400,30 @@ function ConditionalField({
400
400
  const form = useFormContext();
401
401
  const formValues = useWatch({ control });
402
402
  const shouldShow = condition(formValues);
403
- if (!shouldShow) {
403
+ const isAlwaysRegisteredFieldArray = field2 && typeof field2 === "object" && "type" in field2 && field2.type === "fieldArray" && "alwaysRegistered" in field2 && field2.alwaysRegistered === true;
404
+ if (!shouldShow && !isAlwaysRegisteredFieldArray) {
404
405
  return null;
405
406
  }
406
- return /* @__PURE__ */ React5.createElement("div", { className }, /* @__PURE__ */ React5.createElement(
407
- FormField,
407
+ return /* @__PURE__ */ React5.createElement(
408
+ "div",
408
409
  {
409
- config: field2,
410
- form,
411
- submissionState: {
412
- error: void 0,
413
- isSubmitted: false,
414
- isSubmitting: false,
415
- isSuccess: false
410
+ className,
411
+ style: !shouldShow && isAlwaysRegisteredFieldArray ? { display: "none" } : void 0
412
+ },
413
+ /* @__PURE__ */ React5.createElement(
414
+ FormField,
415
+ {
416
+ config: field2,
417
+ form,
418
+ submissionState: {
419
+ error: void 0,
420
+ isSubmitted: false,
421
+ isSubmitting: false,
422
+ isSuccess: false
423
+ }
416
424
  }
417
- }
418
- ));
425
+ )
426
+ );
419
427
  }
420
428
 
421
429
  // src/fields/ContentField.tsx
@@ -1363,8 +1371,13 @@ function FormFieldComponent({
1363
1371
  );
1364
1372
  }
1365
1373
  }
1374
+ let shouldRenderConditionalField = true;
1366
1375
  if ("condition" in fieldConfig && fieldConfig.condition && !fieldConfig.condition(watchedValues)) {
1367
- return null;
1376
+ if ("field" in fieldConfig && fieldConfig.field && typeof fieldConfig.field === "object" && "type" in fieldConfig.field && fieldConfig.field.type === "fieldArray" && "alwaysRegistered" in fieldConfig.field && fieldConfig.field.alwaysRegistered === true) {
1377
+ shouldRenderConditionalField = true;
1378
+ } else {
1379
+ return null;
1380
+ }
1368
1381
  }
1369
1382
  if ("dependsOn" in fieldConfig && fieldConfig.dependsOn) {
1370
1383
  const dependentValue = get(watchedValues, fieldConfig.dependsOn);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rachelallyson/hero-hook-form",
3
- "version": "2.8.0",
3
+ "version": "2.9.1",
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/",