From b33fcab7f9f0af6fdaf1197f44acc891654ac336 Mon Sep 17 00:00:00 2001 From: Jacob Deichert Date: Thu, 16 Apr 2026 10:29:51 -0700 Subject: [PATCH 01/15] Delete legacy v1 InputText --- .../src/InputText/InputText.test.tsx | 179 ------------------ .../components/src/InputText/InputText.tsx | 97 ---------- .../src/InputText/InputText.types.ts | 53 +----- .../__snapshots__/InputText.test.tsx.snap | 116 ------------ packages/components/src/InputText/index.tsx | 42 +--- 5 files changed, 3 insertions(+), 484 deletions(-) delete mode 100644 packages/components/src/InputText/InputText.test.tsx delete mode 100644 packages/components/src/InputText/InputText.tsx delete mode 100644 packages/components/src/InputText/__snapshots__/InputText.test.tsx.snap diff --git a/packages/components/src/InputText/InputText.test.tsx b/packages/components/src/InputText/InputText.test.tsx deleted file mode 100644 index 8c91af7ec2..0000000000 --- a/packages/components/src/InputText/InputText.test.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import React from "react"; -import { fireEvent, render, screen } from "@testing-library/react"; -import { InputText } from "."; -import type { InputTextRef } from "./InputText.types"; - -describe("InputText Version 1", () => { - it("renders a regular input for text and numbers", () => { - const { container } = render(); - expect(container).toMatchSnapshot(); - }); - - it("renders a textarea", () => { - const { container } = render( - , - ); - expect(container).toMatchSnapshot(); - }); - - it("renders a textarea with 4 rows", () => { - const { container } = render( - , - ); - expect(container).toMatchSnapshot(); - }); - - it("should call the handler with the new value", async () => { - const placeholder = "I hold places."; - const newValue = - "The snake which cannot cast its skin has to die. As well the minds which are prevented from changing their opinions; they cease to be mind."; - const newerValue = - "They always say time changes things, but you actually have to change them yourself."; - const changeHandler = jest.fn(); - - const { getByLabelText } = render( - , - ); - - fireEvent.change(getByLabelText(placeholder), { - target: { value: newValue }, - }); - expect(changeHandler).toHaveBeenCalledWith(newValue); - - fireEvent.change(getByLabelText(placeholder), { - target: { value: newerValue }, - }); - expect(changeHandler).toHaveBeenCalledWith(newerValue); - }); - - it("should handle inserting text", () => { - const initial = "Got milk?"; - const result = `${initial}YUP`; - const secondResult = `${initial}YUPsure`; - - const textRef = React.createRef(); - const changeHandler = jest.fn(); - - render( - , - ); - - textRef.current?.insert("YUP"); - expect(changeHandler).toHaveBeenCalledWith(result); - - textRef.current?.insert("sure"); - expect(changeHandler).toHaveBeenCalledWith(secondResult); - }); - - describe("focusing", () => { - it("should focus input text", () => { - const placeholder = "Got milk?"; - - const textRef = React.createRef(); - - const { getByLabelText } = render( - , - ); - - textRef.current?.focus(); - expect(getByLabelText(placeholder)).toHaveFocus(); - }); - - it("supports the autofocus attribute", async () => { - const placeholder = "Got milk?"; - - const { getByLabelText } = render( - , - ); - - expect(getByLabelText(placeholder)).toHaveFocus(); - }); - }); - - it("should scroll into view input text", () => { - const scrollIntoViewMock = jest.fn(); - window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock; - - const placeholder = "Got milk?"; - - const textRef = React.createRef(); - - render(); - - textRef.current?.scrollIntoView(); - expect(scrollIntoViewMock).toHaveBeenCalled(); - }); - - describe("toolbar", () => { - describe("without toolbar", () => { - it("should not render toolbar", () => { - render(); - expect( - screen.queryByTestId("ATL-InputText-Toolbar"), - ).not.toBeInTheDocument(); - }); - }); - describe("with toolbar and toolbarVisibility always", () => { - it("should always render toolbar", () => { - render( - Bar Of Tool} - toolbarVisibility="always" - />, - ); - expect(screen.getByTestId("ATL-InputText-Toolbar")).toBeInTheDocument(); - }); - }); - - describe("with toolbar and toolbarVisibility focus-within", () => { - it("should only render toolbar when focused", () => { - render( - Bar Of Tool} - />, - ); - expect( - screen.queryByTestId("ATL-InputText-Toolbar"), - ).not.toBeInTheDocument(); - - const input = screen.getByLabelText("Favourite movie"); - fireEvent.focus(input); - - expect(screen.getByTestId("ATL-InputText-Toolbar")).toBeInTheDocument(); - }); - }); - describe("with multiline", () => { - describe("with toolbar and toolbarVisibility focus-within", () => { - it("should only render toolbar when focused", () => { - render( - Bar Of Tool} - multiline - />, - ); - expect( - screen.queryByTestId("ATL-InputText-Toolbar"), - ).not.toBeInTheDocument(); - - const input = screen.getByLabelText("Favourite movie"); - fireEvent.focus(input); - - expect( - screen.getByTestId("ATL-InputText-Toolbar"), - ).toBeInTheDocument(); - }); - }); - }); - }); -}); diff --git a/packages/components/src/InputText/InputText.tsx b/packages/components/src/InputText/InputText.tsx deleted file mode 100644 index 75e3b699cf..0000000000 --- a/packages/components/src/InputText/InputText.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import type { Ref } from "react"; -import React, { forwardRef, useImperativeHandle, useRef } from "react"; -// eslint-disable-next-line import/no-deprecated -import type { InputTextLegacyProps, InputTextRef } from "./InputText.types"; -import { useTextAreaResize } from "./useTextAreaResize"; -import type { FieldActionsRef } from "../FormField"; -import { FormField } from "../FormField"; - -function InputTextInternal( - // eslint-disable-next-line import/no-deprecated - props: InputTextLegacyProps, - ref: Ref, -) { - const inputRef = useRef(null); - const actionsRef = useRef(null); - const wrapperRef = useRef(null); - - const { resize, rowRange } = useTextAreaResize({ - rows: props.rows, - value: props.value, - inputRef, - wrapperRef, - }); - - useImperativeHandle(ref, () => ({ - insert: (text: string) => { - insertText(text); - }, - blur: () => { - const input = inputRef.current; - - if (input) { - input.blur(); - } - }, - focus: () => { - const input = inputRef.current; - - if (input) { - input.focus(); - } - }, - scrollIntoView: arg => { - const input = inputRef.current; - - if (input) { - input.scrollIntoView(arg); - } - }, - })); - - return ( - - ); - - function handleChange(newValue: string) { - props.onChange && props.onChange(newValue); - - resize(); - } - - function insertText(text: string) { - const input = inputRef.current; - - if (input) { - insertAtCursor(input, text); - - const newValue = input.value; - actionsRef.current?.setValue(newValue); - props.onChange && props.onChange(newValue); - } - } -} - -export const InputText = forwardRef(InputTextInternal); - -function insertAtCursor( - input: HTMLTextAreaElement | HTMLInputElement, - newText: string, -) { - const start = input.selectionStart || 0; - const end = input.selectionEnd || 0; - const text = input.value; - const before = text.substring(0, start); - const after = text.substring(end, text.length); - input.value = before + newText + after; - input.selectionStart = input.selectionEnd = start + newText.length; - input.focus(); -} diff --git a/packages/components/src/InputText/InputText.types.ts b/packages/components/src/InputText/InputText.types.ts index 75b5a17adc..99ee88c09f 100644 --- a/packages/components/src/InputText/InputText.types.ts +++ b/packages/components/src/InputText/InputText.types.ts @@ -1,5 +1,4 @@ -import type { XOR } from "ts-xor"; -import type { CommonFormFieldProps, FormFieldProps } from "../FormField"; +import type { FormFieldProps } from "../FormField"; import type { FocusEvents, HTMLInputBaseProps, @@ -25,12 +24,6 @@ interface InputLengthConstraint { readonly maxLength?: number; } -export type InputTextVersion = 1 | 2 | undefined; - -/** - * Experimental version 2 of the InputText component. - * Do not use unless you have talked with Atlantis first. - */ export interface InputTextRebuiltProps extends HTMLInputBaseProps, MouseEvents, @@ -88,53 +81,9 @@ export interface InputTextRebuiltProps readonly onEnter?: FormFieldProps["onEnter"]; } -interface BaseProps - extends CommonFormFieldProps, - Pick< - FormFieldProps, - | "autofocus" - | "maxLength" - | "readonly" - | "autocomplete" - | "keyboard" - | "onEnter" - | "onFocus" - | "onBlur" - | "onChange" - | "inputRef" - | "validations" - | "defaultValue" - | "prefix" - | "suffix" - | "toolbar" - | "toolbarVisibility" - | "version" - > { - multiline?: boolean; -} - export interface InputTextRef { insert(text: string): void; blur(): void; focus(): void; scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void; } - -interface MultilineProps extends BaseProps { - /** - * Use this when you're expecting a long answer. - */ - readonly multiline: true; - - /** - * Specifies the visible height of a long answer form field. Can be in the - * form of a single number to set a static height, or an object with a min - * and max keys indicating the minimum number of visible rows, and the - * maximum number of visible rows. - */ - readonly rows?: number | RowRange; -} -/** - * @deprecated Use the v2 InputText component instead (version={2}). - */ -export type InputTextLegacyProps = XOR; diff --git a/packages/components/src/InputText/__snapshots__/InputText.test.tsx.snap b/packages/components/src/InputText/__snapshots__/InputText.test.tsx.snap deleted file mode 100644 index 61b5dd22e7..0000000000 --- a/packages/components/src/InputText/__snapshots__/InputText.test.tsx.snap +++ /dev/null @@ -1,116 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`InputText Version 1 renders a regular input for text and numbers 1`] = ` -
-
-
-
-
- -
- -
-
-
-
-
-
-`; - -exports[`InputText Version 1 renders a textarea 1`] = ` -
-
-
-
-
- -
-