Skip to content

Commit

Permalink
feat(Forms): add innerRef to Field.String for React.ref support (#2679)
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker authored Sep 25, 2023
1 parent 4eda388 commit 930b89d
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ showTabs: true

import DataValueReadwriteProperties from '../../data-value-readwrite-properties.mdx'

## Properties
### Component-specific props

<DataValueReadwriteProperties type="string" />
| Property | Type | Description |
| ------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `string` | _(optional)_ Input DOM element type |
| `multiline` | `boolean` | _(optional)_ True to be able to write in multiple lines (switching from input-element to textarea-element) |
| `leftIcon` | `string` | _(optional)_ For icon at the left side of the text input |
| `rightIcon` | `string` | _(optional)_ For icon at the right side of the text input |
| `inputClassName` | `string` | _(optional)_ Class name set on the &lt;input&gt; DOM element |
| `innerRef` | `React.ref` | _(optional)_ by providing a React.ref we can get the internally used input element (DOM). E.g. `innerRef={myRef}` by using `React.createRef()` or `React.useRef()`. |
| `clear` | `boolean` | _(optional)_ True to have a clickable clear-icon for removing the active value |
| `autoresize` | `boolean` | _(optional)_ For `multiline`, set true to expand when writing longer texts. |
| `autoresizeMaxRows` | `boolean` | _(optional)_ For `multiline`, set how many rows of text can be shown at max. |
| `characterCounter` | `boolean` | _(optional)_ True to show a character counter. |
| `minLength` | `boolean` | _(optional)_ Validation for minimum length of the text (number of characters) |
| `maxLength` | `boolean` | _(optional)_ Validation for maximum length of the text (number of characters) |
| `pattern` | `boolean` | _(optional)_ Validation based on regex pattern |
| `width` | `string` or `false` | _(optional)_ `false` for no width (use browser default), `small`, `medium` or `large` for predefined standard widths, `stretch` for fill available width. |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents` |
| [Space](/uilib/components/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |

### Component-specific props
## Properties

| Property | Type | Description |
| ------------------------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inputClassName` | `string` | _(optional)_ Class name set on the &lt;input&gt; DOM element |
| `type` | `string` | _(optional)_ Input DOM element type |
| `multiline` | `boolean` | _(optional)_ True to be able to write in multiple lines (switching from input-element to textarea-element) |
| `leftIcon` | `string` | _(optional)_ For icon at the left side of the text input |
| `rightIcon` | `string` | _(optional)_ For icon at the right side of the text input |
| `clear` | `boolean` | _(optional)_ True to have a clickable clear-icon for removing the active value |
| `autoresize` | `boolean` | _(optional)_ For `multiline`, set true to expand when writing longer texts. |
| `autoresizeMaxRows` | `boolean` | _(optional)_ For `multiline`, set how many rows of text can be shown at max. |
| `characterCounter` | `boolean` | _(optional)_ True to show a character counter. |
| `minLength` | `boolean` | _(optional)_ Validation for minimum length of the text (number of characters) |
| `maxLength` | `boolean` | _(optional)_ Validation for maximum length of the text (number of characters) |
| `pattern` | `boolean` | _(optional)_ Validation based on regex pattern |
| `width` | `string` or `false` | _(optional)_ `false` for no width (use browser default), `small`, `medium` or `large` for predefined standard widths, `stretch` for fill available width. |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents` |
| [Space](/uilib/components/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |
<DataValueReadwriteProperties type="string" />
5 changes: 1 addition & 4 deletions packages/dnb-eufemia/src/components/textarea/Textarea.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ export type TextareaAutoresizeMaxRows = string | number;
export type TextareaTextareaAttributes = string | Record<string, unknown>;
export type TextareaRows = number | string;
export type TextareaCols = number | string;
export type TextareaInnerRef =
| ((...args: any[]) => any)
| Record<string, unknown>;
export type TextareaTextareaElement =
| ((...args: any[]) => any)
| React.ReactNode;
Expand Down Expand Up @@ -109,7 +106,7 @@ export interface TextareaProps
/**
* By providing a React.ref we can get the internally used Textarea element (DOM). E.g. `inner_ref={myRef}` by using `React.createRef()` or `React.useRef()`.
*/
inner_ref?: TextareaInnerRef;
inner_ref?: React.Ref;
className?: string;
textarea_element?: TextareaTextareaElement;
children?: TextareaChildren;
Expand Down
7 changes: 6 additions & 1 deletion packages/dnb-eufemia/src/extensions/forms/Field/String.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ interface ErrorMessages {
}
export type Props = FieldHelpProps &
FieldProps<string, undefined | string, ErrorMessages> & {
inputClassName?: string
type?: InputProps['type']
multiline?: boolean
leftIcon?: string
rightIcon?: string
inputClassName?: string
innerRef?: React.RefObject<HTMLInputElement | HTMLTextAreaElement>
clear?: boolean
autoresize?: boolean
autoresizeMaxRows?: number
Expand Down Expand Up @@ -81,6 +82,7 @@ function StringComponent(props: Props) {
const {
id,
className,
innerRef,
inputClassName,
layout,
type,
Expand Down Expand Up @@ -149,6 +151,7 @@ function StringComponent(props: Props) {
autoresize_max_rows={autoresizeMaxRows}
disabled={disabled}
stretch={width !== undefined}
inner_ref={innerRef}
/>
) : mask ? (
<InputMasked
Expand All @@ -169,6 +172,7 @@ function StringComponent(props: Props) {
on_change={handleChange}
disabled={disabled}
stretch={width !== undefined}
inner_ref={innerRef}
/>
) : (
<Input
Expand All @@ -190,6 +194,7 @@ function StringComponent(props: Props) {
on_change={handleChange}
disabled={disabled}
stretch={width !== undefined}
inner_ref={innerRef}
/>
)}
</FieldBlock>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react'
import { render } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import OrganizationNumber from '../OrganizationNumber'

describe('Field.OrganizationNumber', () => {
it('should have Norwegian mask', async () => {
render(<OrganizationNumber />)

const element = document.querySelector('input')
await userEvent.type(element, '123456789')
expect(element.value).toBe('123 456 789')
})

it('should have medium width', () => {
render(<OrganizationNumber />)

const element = document.querySelector(
'.dnb-forms-field-block__contents'
)
expect(element.className).toContain(
'dnb-forms-field-block__contents--width-medium'
)
})

it('should have disabled autocomplete', () => {
render(<OrganizationNumber />)

const element = document.querySelector('input')
expect(element.autocomplete).toBe('off')
})

it('should link for and label', () => {
render(<OrganizationNumber />)

const labelElement = document.querySelector('label')
const inputElement = document.querySelector('input')

expect(inputElement.getAttribute('id')).toBe(
labelElement.getAttribute('for')
)
})

it('should have default label', () => {
render(<OrganizationNumber />)

const element = document.querySelector('label')
expect(element.textContent).toBe('Organisasjonsnummer')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -622,4 +622,20 @@ describe('Field.String', () => {
})
})
})

it('gets valid ref element', () => {
const id = 'unique'
let ref: React.RefObject<HTMLInputElement>

const MockComponent = () => {
ref = React.useRef()
return <Field.String id={id} innerRef={ref} />
}

render(<MockComponent />)

expect(ref.current instanceof HTMLInputElement).toBe(true)
expect(ref.current.id).toBe(id)
expect(ref.current.tagName).toBe('INPUT')
})
})

0 comments on commit 930b89d

Please sign in to comment.