From a0231b0eed1cf129523a3367f50bae2c302709e2 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Tue, 16 Jul 2024 18:58:44 +0900 Subject: [PATCH 01/12] fix: sync the inputValue with domRef.current.value when hovering the input --- packages/components/input/src/use-input.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/components/input/src/use-input.ts b/packages/components/input/src/use-input.ts index 0cc2102725..86ffef3f7c 100644 --- a/packages/components/input/src/use-input.ts +++ b/packages/components/input/src/use-input.ts @@ -205,7 +205,13 @@ export function useInput { + if (!domRef.current) return; + setInputValue(domRef.current.value); + }, + }); const {focusProps: clearFocusProps, isFocusVisible: isClearButtonFocusVisible} = useFocusRing(); From f5d17736cca37e0b0d19acf06f7435fdfcc1ef21 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Tue, 16 Jul 2024 19:21:35 +0900 Subject: [PATCH 02/12] chore: add changeset --- .changeset/angry-icons-jump.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/angry-icons-jump.md diff --git a/.changeset/angry-icons-jump.md b/.changeset/angry-icons-jump.md new file mode 100644 index 0000000000..628b917a56 --- /dev/null +++ b/.changeset/angry-icons-jump.md @@ -0,0 +1,5 @@ +--- +"@nextui-org/input": patch +--- + +sync the inputValue with domRef.current.value when hovering the input From 9313561bfad9259f0cec97e68d51029cd66ce868 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Tue, 16 Jul 2024 21:13:31 +0900 Subject: [PATCH 03/12] test: add test code --- .../components/input/__tests__/input.test.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index 043de2da6e..f031f13e1f 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -180,6 +180,23 @@ describe("Input", () => { expect(inputs[1]).toBeVisible(); }); + + it("should sync ref.current.value with input's value after hovering over the input", async () => { + const ref = React.createRef(); + + const {container} = render(); + const inputBase = container.querySelector("[data-slot='base']"); + const input = inputBase && inputBase.querySelector("input"); + const user = userEvent.setup(); + + if (!input) throw new Error("input is null"); + if (!ref.current) throw new Error("ref is null"); + + ref.current.value = "new value"; + await user.hover(inputBase); + + expect(input).toHaveValue("new value"); + }); }); describe("Input with React Hook Form", () => { From 75365abba6d839d110145334ef79d9cd78cb3e5a Mon Sep 17 00:00:00 2001 From: jijiseong Date: Tue, 16 Jul 2024 21:17:43 +0900 Subject: [PATCH 04/12] test: refactor test --- packages/components/input/__tests__/input.test.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index f031f13e1f..dfa4889679 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -189,11 +189,12 @@ describe("Input", () => { const input = inputBase && inputBase.querySelector("input"); const user = userEvent.setup(); - if (!input) throw new Error("input is null"); - if (!ref.current) throw new Error("ref is null"); + expect(inputBase).not.toBeNull(); + expect(input).not.toBeNull(); + expect(ref.current).not.toBeNull(); - ref.current.value = "new value"; - await user.hover(inputBase); + ref.current!.value = "new value"; + await user.hover(inputBase!); expect(input).toHaveValue("new value"); }); From 9121dc46ef4c2b1326fe1a2156aaebe324938f1b Mon Sep 17 00:00:00 2001 From: jijiseong Date: Tue, 16 Jul 2024 21:19:14 +0900 Subject: [PATCH 05/12] test: refactor test --- packages/components/input/__tests__/input.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index dfa4889679..2bb1ec490b 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -186,7 +186,8 @@ describe("Input", () => { const {container} = render(); const inputBase = container.querySelector("[data-slot='base']"); - const input = inputBase && inputBase.querySelector("input"); + const input = inputBase?.querySelector("input"); + const user = userEvent.setup(); expect(inputBase).not.toBeNull(); From 528d579cebf661a91df138740fbb4d85d24417a3 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Wed, 17 Jul 2024 14:23:43 +0900 Subject: [PATCH 06/12] chore: add issue link in changeset --- .changeset/angry-icons-jump.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/angry-icons-jump.md b/.changeset/angry-icons-jump.md index 628b917a56..887c5c1b0a 100644 --- a/.changeset/angry-icons-jump.md +++ b/.changeset/angry-icons-jump.md @@ -2,4 +2,4 @@ "@nextui-org/input": patch --- -sync the inputValue with domRef.current.value when hovering the input +sync the inputValue with domRef.current.value when hovering the input (#3024, #3436) From cf54ff9a778ae4bf441343ba1eaaff793068677c Mon Sep 17 00:00:00 2001 From: jijiseong Date: Thu, 18 Jul 2024 16:52:54 +0900 Subject: [PATCH 07/12] refactor: handled the case for tabbing out --- packages/components/input/src/use-input.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/components/input/src/use-input.ts b/packages/components/input/src/use-input.ts index 86ffef3f7c..fafff8ce4d 100644 --- a/packages/components/input/src/use-input.ts +++ b/packages/components/input/src/use-input.ts @@ -158,6 +158,10 @@ export function useInput { + setInputValue(domRef.current?.value); + }; + // if we use `react-hook-form`, it will set the input value using the ref in register // i.e. setting ref.current.value to something which is uncontrolled // hence, sync the state with `ref.current.value` @@ -207,10 +211,7 @@ export function useInput { - if (!domRef.current) return; - setInputValue(domRef.current.value); - }, + onHoverStart: syncRefValueToInputValue, }); const {focusProps: clearFocusProps, isFocusVisible: isClearButtonFocusVisible} = useFocusRing(); @@ -222,6 +223,7 @@ export function useInput Date: Thu, 18 Jul 2024 16:53:29 +0900 Subject: [PATCH 08/12] test: refactor hover -> click --- packages/components/input/__tests__/input.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index 2bb1ec490b..ce517b9195 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -15,7 +15,7 @@ describe("Input", () => { it("ref should be forwarded", () => { const ref = React.createRef(); - render(); + render(); expect(ref.current).not.toBeNull(); }); @@ -181,7 +181,7 @@ describe("Input", () => { expect(inputs[1]).toBeVisible(); }); - it("should sync ref.current.value with input's value after hovering over the input", async () => { + it("should sync ref.current.value with input's value after clicking the input", async () => { const ref = React.createRef(); const {container} = render(); @@ -195,8 +195,7 @@ describe("Input", () => { expect(ref.current).not.toBeNull(); ref.current!.value = "new value"; - await user.hover(inputBase!); - + await user.click(inputBase!); expect(input).toHaveValue("new value"); }); }); From b8f8ecfcf1dedb9bb9b238b893172f54857920c0 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Thu, 18 Jul 2024 17:15:50 +0900 Subject: [PATCH 09/12] chore: fix typo --- packages/components/input/__tests__/input.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index ce517b9195..7f5cc1fa61 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -15,7 +15,7 @@ describe("Input", () => { it("ref should be forwarded", () => { const ref = React.createRef(); - render(); + render(); expect(ref.current).not.toBeNull(); }); From cd9d9db2bb0a71212d3d663ad9b20e76c1443023 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Thu, 18 Jul 2024 17:16:10 +0900 Subject: [PATCH 10/12] chore: modify change set --- .changeset/angry-icons-jump.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/angry-icons-jump.md b/.changeset/angry-icons-jump.md index 887c5c1b0a..f752dca1d0 100644 --- a/.changeset/angry-icons-jump.md +++ b/.changeset/angry-icons-jump.md @@ -2,4 +2,4 @@ "@nextui-org/input": patch --- -sync the inputValue with domRef.current.value when hovering the input (#3024, #3436) +sync the inputValue with domRef.current.value when hovering or tabbing the input (#3024, #3436) From 68050a8ffd86c92e645ddcec45469ba135c9ed8f Mon Sep 17 00:00:00 2001 From: jijiseong Date: Thu, 18 Jul 2024 18:55:06 +0900 Subject: [PATCH 11/12] test: refactor test --- .../components/input/__tests__/input.test.tsx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index 7f5cc1fa61..7e54756abe 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import {render, renderHook, fireEvent} from "@testing-library/react"; +import {render, renderHook, fireEvent, act} from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import {useForm} from "react-hook-form"; @@ -182,20 +182,26 @@ describe("Input", () => { }); it("should sync ref.current.value with input's value after clicking the input", async () => { + const user = userEvent.setup(); const ref = React.createRef(); const {container} = render(); - const inputBase = container.querySelector("[data-slot='base']"); - const input = inputBase?.querySelector("input"); - const user = userEvent.setup(); + expect(ref.current).not.toBeNull(); + + const inputBase = container.querySelector("[data-slot='base']"); expect(inputBase).not.toBeNull(); + + const input = container.querySelector("input"); + expect(input).not.toBeNull(); - expect(ref.current).not.toBeNull(); ref.current!.value = "new value"; - await user.click(inputBase!); + + await act(async () => { + await user.click(inputBase!); + }); expect(input).toHaveValue("new value"); }); }); From f6afb9655f5eb4744740784b54e980cb41776710 Mon Sep 17 00:00:00 2001 From: jijiseong Date: Thu, 18 Jul 2024 19:07:25 +0900 Subject: [PATCH 12/12] test: add test for hovering case --- .../components/input/__tests__/input.test.tsx | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/components/input/__tests__/input.test.tsx b/packages/components/input/__tests__/input.test.tsx index 7e54756abe..c5199dde71 100644 --- a/packages/components/input/__tests__/input.test.tsx +++ b/packages/components/input/__tests__/input.test.tsx @@ -206,6 +206,30 @@ describe("Input", () => { }); }); +it("should sync ref.current.value with input's value after hovering the input", async () => { + const user = userEvent.setup(); + const ref = React.createRef(); + + const {container} = render(); + + expect(ref.current).not.toBeNull(); + + const inputBase = container.querySelector("[data-slot='base']"); + + expect(inputBase).not.toBeNull(); + + const input = container.querySelector("input"); + + expect(input).not.toBeNull(); + + ref.current!.value = "new value"; + + await act(async () => { + await user.hover(inputBase!); + }); + expect(input).toHaveValue("new value"); +}); + describe("Input with React Hook Form", () => { let input1: HTMLInputElement; let input2: HTMLInputElement;