diff --git a/packages/pelagos/__tests__/formFields/TextArea-test.js b/packages/pelagos/__tests__/formFields/TextArea-test.js
new file mode 100644
index 00000000..2674c7fc
--- /dev/null
+++ b/packages/pelagos/__tests__/formFields/TextArea-test.js
@@ -0,0 +1,54 @@
+import {shallow} from 'enzyme';
+
+import TextArea from '../../src/formFields/TextArea';
+
+jest.unmock('../../src/formFields/TextArea');
+
+describe('TextArea', () => {
+ describe('rendering', () => {
+ it('renders expected elements', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ it('renders expected elements when className is set', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ it('renders expected elements when resize is set', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ it('renders expected elements when error is set', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+ });
+
+ describe('behaviour', () => {
+ it('calls onChange when a change event is fired', () => {
+ const onChange = jest.fn();
+ const event = {target: {value: 'test'}};
+ const wrapper = shallow();
+ wrapper.find('[as="textarea"]').simulate('change', event);
+ expect(onChange.mock.calls).toEqual([['test']]);
+ });
+ });
+});
diff --git a/packages/pelagos/__tests__/formFields/TextAreaField-test.js b/packages/pelagos/__tests__/formFields/TextAreaField-test.js
index 84bf47e3..ae26d573 100644
--- a/packages/pelagos/__tests__/formFields/TextAreaField-test.js
+++ b/packages/pelagos/__tests__/formFields/TextAreaField-test.js
@@ -49,22 +49,7 @@ describe('TextAreaField', () => {
expect(wrapper.getElement()).toMatchSnapshot();
});
- it('does not add the resize class if the resize is true', () => {
- const wrapper = shallow(
-
- );
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-
- it('renders expected elements when showCounter is true', () => {
+ it('renders expected elements when showCounter is set', () => {
const wrapper = shallow(
{
);
expect(wrapper.getElement()).toMatchSnapshot();
});
-
- it('adds the error class if the error is set', () => {
- const wrapper = shallow(
-
- );
- expect(wrapper.getElement()).toMatchSnapshot();
- });
- });
-
- describe('behaviour', () => {
- it('calls onChange when a change event is fired', () => {
- const onChange = jest.fn();
- const event = {target: {value: 'test'}};
- const wrapper = shallow();
- wrapper.find('[as="textarea"]').simulate('change', event);
- expect(onChange.mock.calls).toEqual([['test']]);
- });
});
});
diff --git a/packages/pelagos/__tests__/formFields/TextInput-test.js b/packages/pelagos/__tests__/formFields/TextInput-test.js
new file mode 100644
index 00000000..3872459d
--- /dev/null
+++ b/packages/pelagos/__tests__/formFields/TextInput-test.js
@@ -0,0 +1,67 @@
+import {shallow} from 'enzyme';
+
+import TextInput from '../../src/formFields/TextInput';
+
+jest.unmock('../../src/formFields/TextInput');
+
+describe('TextInput', () => {
+ describe('rendering', () => {
+ it('renders expected elements', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ it('renders expected elements when className is set', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ it('renders expected elements when error is set', () => {
+ const wrapper = shallow(
+
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+ });
+
+ describe('behaviour', () => {
+ it('calls onChange when a change event is fired', () => {
+ const onChange = jest.fn();
+ const event = {target: {value: 'test'}};
+ const wrapper = shallow();
+ wrapper.simulate('change', event);
+ expect(onChange.mock.calls).toEqual([['test']]);
+ });
+ });
+});
diff --git a/packages/pelagos/__tests__/formFields/TextInputField-test.js b/packages/pelagos/__tests__/formFields/TextInputField-test.js
index bb545227..0963eff4 100644
--- a/packages/pelagos/__tests__/formFields/TextInputField-test.js
+++ b/packages/pelagos/__tests__/formFields/TextInputField-test.js
@@ -4,7 +4,6 @@ import TextInputField from '../../src/formFields/TextInputField';
import useRandomId from '../../src/hooks/useRandomId';
jest.unmock('../../src/formFields/TextInputField');
-jest.mock('lodash-es/debounce', () => jest.fn((f) => f));
useRandomId.mockReturnValue('random-id');
@@ -29,23 +28,6 @@ describe('TextInputField', () => {
expect(useRandomId.mock.calls).toEqual([['test']]);
});
- it('renders expected elements when value is empty', () => {
- const wrapper = shallow(
-
- );
- expect(wrapper.getElement()).toMatchSnapshot();
- });
-
it('renders expected elements when className is set', () => {
const wrapper = shallow(
{
value="value"
placeholder="placeholder"
maxLength={10}
- disabled={false}
onChange={jest.fn()}
/>
);
expect(wrapper.getElement()).toMatchSnapshot();
});
- it('adds the error class if the error is set', () => {
+ it('renders expected elements when error is set', () => {
const wrapper = shallow(
{
value="value"
placeholder="placeholder"
maxLength={10}
- disabled={false}
helperText="Helper text"
error="Error"
onChange={jest.fn()}
@@ -83,14 +63,4 @@ describe('TextInputField', () => {
expect(wrapper.getElement()).toMatchSnapshot();
});
});
-
- describe('behaviour', () => {
- it('calls onChange when a change event is fired', () => {
- const onChange = jest.fn();
- const event = {target: {value: 'test'}};
- const wrapper = shallow();
- wrapper.find('[as="input"]').simulate('change', event);
- expect(onChange.mock.calls).toEqual([['test']]);
- });
- });
});
diff --git a/packages/pelagos/__tests__/formFields/__snapshots__/TextArea-test.js.snap b/packages/pelagos/__tests__/formFields/__snapshots__/TextArea-test.js.snap
new file mode 100644
index 00000000..ef3c7438
--- /dev/null
+++ b/packages/pelagos/__tests__/formFields/__snapshots__/TextArea-test.js.snap
@@ -0,0 +1,51 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`TextArea rendering renders expected elements 1`] = `
+
+`;
+
+exports[`TextArea rendering renders expected elements when className is set 1`] = `
+
+`;
+
+exports[`TextArea rendering renders expected elements when error is set 1`] = `
+
+`;
+
+exports[`TextArea rendering renders expected elements when resize is set 1`] = `
+
+`;
diff --git a/packages/pelagos/__tests__/formFields/__snapshots__/TextAreaField-test.js.snap b/packages/pelagos/__tests__/formFields/__snapshots__/TextAreaField-test.js.snap
index 85ae4e51..c4657c54 100644
--- a/packages/pelagos/__tests__/formFields/__snapshots__/TextAreaField-test.js.snap
+++ b/packages/pelagos/__tests__/formFields/__snapshots__/TextAreaField-test.js.snap
@@ -1,51 +1,5 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
-exports[`TextAreaField rendering adds the error class if the error is set 1`] = `
-
-
-
-`;
-
-exports[`TextAreaField rendering does not add the resize class if the resize is true 1`] = `
-
-
-
-`;
-
exports[`TextAreaField rendering renders expected elements 1`] = `
-
@@ -79,21 +31,19 @@ exports[`TextAreaField rendering renders expected elements when className is set
htmlFor="random-id"
label="Label"
>
-
`;
-exports[`TextAreaField rendering renders expected elements when showCounter is true 1`] = `
+exports[`TextAreaField rendering renders expected elements when showCounter is set 1`] = `
-
@@ -123,14 +71,12 @@ exports[`TextAreaField rendering renders expected elements when value is empty 1
htmlFor="random-id"
label="Label"
>
-
diff --git a/packages/pelagos/__tests__/formFields/__snapshots__/TextInput-test.js.snap b/packages/pelagos/__tests__/formFields/__snapshots__/TextInput-test.js.snap
new file mode 100644
index 00000000..fc72b278
--- /dev/null
+++ b/packages/pelagos/__tests__/formFields/__snapshots__/TextInput-test.js.snap
@@ -0,0 +1,45 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`TextInput rendering renders expected elements 1`] = `
+
+`;
+
+exports[`TextInput rendering renders expected elements when className is set 1`] = `
+
+`;
+
+exports[`TextInput rendering renders expected elements when error is set 1`] = `
+
+`;
diff --git a/packages/pelagos/__tests__/formFields/__snapshots__/TextInputField-test.js.snap b/packages/pelagos/__tests__/formFields/__snapshots__/TextInputField-test.js.snap
index 2f861038..ef6dc17b 100644
--- a/packages/pelagos/__tests__/formFields/__snapshots__/TextInputField-test.js.snap
+++ b/packages/pelagos/__tests__/formFields/__snapshots__/TextInputField-test.js.snap
@@ -1,31 +1,5 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
-exports[`TextInputField rendering adds the error class if the error is set 1`] = `
-
-
-
-`;
-
exports[`TextInputField rendering renders expected elements 1`] = `
-
@@ -59,16 +31,13 @@ exports[`TextInputField rendering renders expected elements when className is se
htmlFor="random-id"
label="Label"
>
-
`;
-exports[`TextInputField rendering renders expected elements when value is empty 1`] = `
+exports[`TextInputField rendering renders expected elements when error is set 1`] = `
-
`;
diff --git a/packages/pelagos/src/formFields/TextArea.d.ts b/packages/pelagos/src/formFields/TextArea.d.ts
new file mode 100644
index 00000000..e6ab7581
--- /dev/null
+++ b/packages/pelagos/src/formFields/TextArea.d.ts
@@ -0,0 +1,26 @@
+import type {FunctionComponent, HTMLProps} from 'react';
+
+interface TextAreaProps extends Omit, 'value' | 'onChange'> {
+ /** The component ID. */
+ id?: string;
+ /** The component class name(s). */
+ className?: string;
+ /** The field value. */
+ value?: string;
+ /** The placeholder text. */
+ placeholder?: string;
+ /** Whether the field is required. */
+ required?: boolean;
+ /** Whether the field can be resized. */
+ resize?: boolean;
+ /** The maximum text length. */
+ maxLength?: number;
+ /** Whether the component is in error. */
+ error?: boolean;
+ /** Function invoked when the value changes. */
+ onChange: (value: string) => void;
+}
+
+/** A text area input. */
+declare const TextArea: FunctionComponent;
+export default TextArea;
diff --git a/packages/pelagos/src/formFields/TextArea.js b/packages/pelagos/src/formFields/TextArea.js
new file mode 100644
index 00000000..d5395fb1
--- /dev/null
+++ b/packages/pelagos/src/formFields/TextArea.js
@@ -0,0 +1,43 @@
+import {useCallback} from 'react';
+import PropTypes from 'prop-types';
+
+import Layer from '../components/Layer';
+
+import './TextAreaField.less';
+
+/** A text area input. */
+const TextAreaField = ({className, required, resize, error, onChange, ...props}) => (
+ onChange(event.target.value), [onChange])}
+ />
+);
+
+TextAreaField.propTypes = {
+ /** The component ID. */
+ id: PropTypes.string,
+ /** The component class name(s). */
+ className: PropTypes.string,
+ /** The field value. */
+ value: PropTypes.string,
+ /** The placeholder text. */
+ placeholder: PropTypes.string,
+ /** Whether the field is required. */
+ required: PropTypes.bool,
+ /** Whether the field can be resized. */
+ resize: PropTypes.bool,
+ /** The maximum text length. */
+ maxLength: PropTypes.number,
+ /** Whether the component is in error. */
+ error: PropTypes.bool,
+ /** Function invoked when the value changes. */
+ onChange: PropTypes.func.isRequired,
+};
+
+export default TextAreaField;
diff --git a/packages/pelagos/src/formFields/TextArea.stories.js b/packages/pelagos/src/formFields/TextArea.stories.js
new file mode 100644
index 00000000..46c5dc9b
--- /dev/null
+++ b/packages/pelagos/src/formFields/TextArea.stories.js
@@ -0,0 +1,36 @@
+import {useState} from 'react';
+import {action} from 'storybook/actions';
+
+import WithLayers from '../../templates/WithLayers';
+
+import TextArea from './TextArea';
+
+const handleChange = action('onChange');
+
+export default {
+ title: 'Components/TextArea',
+ component: TextArea,
+ render: (args) => {
+ const [value, setValue] = useState(args.value);
+ return ;
+ },
+};
+
+export const Default = {
+ args: {'aria-label': 'Default', value: 'Alpha'},
+};
+
+export const Empty = {
+ args: {'aria-label': 'Empty', placeholder: 'Placeholder'},
+};
+
+export const Error = {
+ args: {'aria-label': 'Error', value: 'Alpha', error: true},
+};
+
+export const _WithLayers = {
+ render: () => {() => },
+ parameters: {
+ controls: {hideNoControlsWarning: true},
+ },
+};
diff --git a/packages/pelagos/src/formFields/TextAreaField.js b/packages/pelagos/src/formFields/TextAreaField.js
index 3f6b1dd2..85d3d650 100644
--- a/packages/pelagos/src/formFields/TextAreaField.js
+++ b/packages/pelagos/src/formFields/TextAreaField.js
@@ -1,10 +1,10 @@
-import {useCallback} from 'react';
import PropTypes from 'prop-types';
-import Layer from '../components/Layer';
import useRandomId from '../hooks/useRandomId';
import FieldWrapper from './FieldWrapper';
+import TextArea from './TextArea';
+
import './TextAreaField.less';
/** A text area form field. */
@@ -14,7 +14,6 @@ const TextAreaField = ({
label,
value,
required,
- resize,
maxLength,
showCounter,
helperText,
@@ -34,19 +33,15 @@ const TextAreaField = ({
helperId={helperId}
helperText={helperText}
error={error}>
- onChange(event.target.value), [onChange])}
+ onChange={onChange}
/>
);
diff --git a/packages/pelagos/src/formFields/TextInput.d.ts b/packages/pelagos/src/formFields/TextInput.d.ts
new file mode 100644
index 00000000..eb9f21ca
--- /dev/null
+++ b/packages/pelagos/src/formFields/TextInput.d.ts
@@ -0,0 +1,34 @@
+import type {FunctionComponent, HTMLProps} from 'react';
+
+interface TextInputProps extends Omit, 'value' | 'onChange'> {
+ /** The component ID. */
+ id?: string;
+ /** The component class name(s). */
+ className?: string;
+ /** The input type. */
+ type?: string;
+ /** The input name. */
+ name?: string;
+ /** The auto-complete option. */
+ autoComplete?: string;
+ /** The field value. */
+ value?: number | string | null;
+ /** The placeholder text. */
+ placeholder?: string;
+ /** The maximum text length. */
+ maxLength?: number;
+ /** Whether the field focused on display. */
+ autoFocus?: boolean;
+ /** Whether the field is disabled. */
+ disabled?: boolean;
+ /** Whether the field is required. */
+ required?: boolean;
+ /** Whether the component is in error. */
+ error?: boolean;
+ /** Function invoked when the value changes. */
+ onChange: (value: string) => void;
+}
+
+/** A text input. */
+declare const TextInput: FunctionComponent;
+export default TextInput;
diff --git a/packages/pelagos/src/formFields/TextInput.js b/packages/pelagos/src/formFields/TextInput.js
new file mode 100644
index 00000000..c4c5d623
--- /dev/null
+++ b/packages/pelagos/src/formFields/TextInput.js
@@ -0,0 +1,50 @@
+import {useCallback} from 'react';
+import PropTypes from 'prop-types';
+
+import Layer from '../components/Layer';
+
+import './TextInputField.less';
+
+/** A text input. */
+const TextInputField = ({className, type = 'text', required, error, onChange, ...props}) => (
+ onChange(event.target.value), [onChange])}
+ />
+);
+
+TextInputField.propTypes = {
+ /** The component ID. */
+ id: PropTypes.string,
+ /** The component class name(s). */
+ className: PropTypes.string,
+ /** The input type. */
+ type: PropTypes.string,
+ /** The input name. */
+ name: PropTypes.string,
+ /** The auto-complete option. */
+ autoComplete: PropTypes.string,
+ /** The field value. */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ /** The placeholder text. */
+ placeholder: PropTypes.string,
+ /** The maximum text length. */
+ maxLength: PropTypes.number,
+ /** Whether the field focused on display. */
+ autoFocus: PropTypes.bool,
+ /** Whether the field is disabled. */
+ disabled: PropTypes.bool,
+ /** Whether the field is required. */
+ required: PropTypes.bool,
+ /** Whether the component is in error. */
+ error: PropTypes.bool,
+ /** Function invoked when the value changes. */
+ onChange: PropTypes.func.isRequired,
+};
+
+export default TextInputField;
diff --git a/packages/pelagos/src/formFields/TextInput.stories.js b/packages/pelagos/src/formFields/TextInput.stories.js
new file mode 100644
index 00000000..a2c13f46
--- /dev/null
+++ b/packages/pelagos/src/formFields/TextInput.stories.js
@@ -0,0 +1,44 @@
+import {useState} from 'react';
+import {action} from 'storybook/actions';
+
+import WithLayers from '../../templates/WithLayers';
+
+import TextInput from './TextInput';
+
+const handleChange = action('onChange');
+
+export default {
+ title: 'Components/TextInput',
+ component: TextInput,
+ render: (args) => {
+ const [value, setValue] = useState(args.value);
+ return ;
+ },
+};
+
+export const Default = {
+ args: {'aria-label': 'Default', value: 'Alpha'},
+};
+
+export const Empty = {
+ args: {'aria-label': 'Empty', placeholder: 'Placeholder'},
+};
+
+export const Disabled = {
+ args: {'aria-label': 'Disabled', value: 'Alpha', disabled: true},
+};
+
+export const ReadOnly = {
+ args: {'aria-label': 'Read-Only', value: 'Alpha', readOnly: true},
+};
+
+export const Error = {
+ args: {'aria-label': 'Error', value: 'Alpha', required: true, error: true},
+};
+
+export const _WithLayers = {
+ render: () => {() => },
+ parameters: {
+ controls: {hideNoControlsWarning: true},
+ },
+};
diff --git a/packages/pelagos/src/formFields/TextInputField.js b/packages/pelagos/src/formFields/TextInputField.js
index 401acabc..5c6c7367 100644
--- a/packages/pelagos/src/formFields/TextInputField.js
+++ b/packages/pelagos/src/formFields/TextInputField.js
@@ -1,26 +1,14 @@
-import {useCallback} from 'react';
import PropTypes from 'prop-types';
-import Layer from '../components/Layer';
import useRandomId from '../hooks/useRandomId';
import FieldWrapper from './FieldWrapper';
+import TextInput from './TextInput';
import './TextInputField.less';
/** A text input form field. */
-const TextInputField = ({
- id,
- className,
- label,
- type = 'text',
- value,
- required,
- helperText,
- error,
- onChange,
- ...props
-}) => {
+const TextInputField = ({id, className, label, required, helperText, error, onChange, ...props}) => {
id = useRandomId(id);
const helperId = `${id}-helper`;
return (
@@ -32,17 +20,13 @@ const TextInputField = ({
helperId={helperId}
helperText={helperText}
error={error}>
- onChange(event.target.value), [onChange])}
+ onChange={onChange}
/>
);
diff --git a/packages/pelagos/src/formFields/index.d.ts b/packages/pelagos/src/formFields/index.d.ts
index e74adc18..d38a122b 100644
--- a/packages/pelagos/src/formFields/index.d.ts
+++ b/packages/pelagos/src/formFields/index.d.ts
@@ -5,6 +5,8 @@ export {default as FieldHelper} from './FieldHelper';
export {default as FieldWrapper} from './FieldWrapper';
export {default as OutputField} from './OutputField';
export {default as TagInputField} from './TagInputField';
+export {default as TextArea} from './TextArea';
export {default as TextAreaField} from './TextAreaField';
+export {default as TextInput} from './TextInput';
export {default as TextInputField} from './TextInputField';
export {default as ToggleField} from './ToggleField';
diff --git a/packages/pelagos/src/formFields/index.js b/packages/pelagos/src/formFields/index.js
index e74adc18..d38a122b 100644
--- a/packages/pelagos/src/formFields/index.js
+++ b/packages/pelagos/src/formFields/index.js
@@ -5,6 +5,8 @@ export {default as FieldHelper} from './FieldHelper';
export {default as FieldWrapper} from './FieldWrapper';
export {default as OutputField} from './OutputField';
export {default as TagInputField} from './TagInputField';
+export {default as TextArea} from './TextArea';
export {default as TextAreaField} from './TextAreaField';
+export {default as TextInput} from './TextInput';
export {default as TextInputField} from './TextInputField';
export {default as ToggleField} from './ToggleField';