diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/Examples.tsx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/Examples.tsx index 2d3b256c7bb..63f97c8dfc5 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/Examples.tsx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/Examples.tsx @@ -8,7 +8,7 @@ export const Empty = () => { console.log('onFocus', value)} onBlur={(value) => console.log('onBlur', value)} - onChange={(value) => console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} onCountryCodeChange={(countryCode) => console.log('onCountryCodeChange', countryCode) } @@ -25,7 +25,7 @@ export const Placeholder = () => { console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} /> ) @@ -36,7 +36,7 @@ export const Label = () => { console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} /> ) @@ -48,7 +48,7 @@ export const LabelAndValue = () => { console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} /> ) @@ -58,7 +58,7 @@ export const WithHelp = () => { return ( console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} help={{ title: 'Help is available', contents: @@ -75,7 +75,7 @@ export const Disabled = () => { console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} disabled /> @@ -88,7 +88,7 @@ export const Error = () => { console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} error={new FormError('This is what is wrong...')} /> @@ -101,7 +101,7 @@ export const ValidationRequired = () => { console.log('onChange', value)} + onChange={(...args) => console.log('onChange', ...args)} required /> diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/info.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/info.mdx index cab92e83f0f..f4e72f83691 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/info.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/info.mdx @@ -12,3 +12,15 @@ render() ``` There is a corresponding [Value.PhoneNumber](/uilib/extensions/forms/create-component/Value/PhoneNumber) component. + +## Value + +This component behaves as "one single component". Therefor it combines the country code and the number to a single string during an event callback. + +Also, the `value` property should be a string with the country code, separated from the main number by a space. + +The component returns the `emptyValue` when no number is set, which defaults to `undefined`. + +### Default country code + +The default country code is set to `+47`. diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/properties.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/properties.mdx index 83611ff99e1..ad454a6a356 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/properties.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/PhoneNumber/properties.mdx @@ -21,11 +21,5 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties. diff --git a/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.d.ts b/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.d.ts index 9070f94668f..4d61e9f94d8 100644 --- a/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.d.ts +++ b/packages/dnb-eufemia/src/components/autocomplete/Autocomplete.d.ts @@ -125,7 +125,7 @@ export interface AutocompleteProps */ keep_value?: boolean; /** - * Use `true` to not remove the selected value/key on input blur, if it is invalid. By default, the typed value will disappear / replaced by a selected value from the data list during the input field blur. Defaults to `false`. + * Use `true` to not remove selected item on input blur, when the input value is empty. Defaults to `false`. */ keep_selection?: boolean; /** diff --git a/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/PhoneNumber.tsx b/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/PhoneNumber.tsx index 3c0453ca398..ef79d1a9e25 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/PhoneNumber.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/PhoneNumber.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useContext, useCallback } from 'react' +import React, { useMemo, useContext, useCallback, useEffect } from 'react' import { Autocomplete, Flex } from '../../../../components' import { InputMaskedProps } from '../../../../components/InputMasked' import classnames from 'classnames' @@ -11,7 +11,7 @@ import { pickSpacingProps } from '../../../../components/flex/utils' import SharedContext from '../../../../shared/Context' export type Props = FieldHelpProps & - FieldProps & { + FieldProps & { countryCodeFieldClassName?: string numberFieldClassName?: string countryCodePlaceholder?: string @@ -27,9 +27,14 @@ export type Props = FieldHelpProps & noAnimation?: boolean } +// Important for the default value to be defined here, and not after the useDataValue call, to avoid the UI jumping +// back to +47 once the user empty the field so handleChange send out undefined. +const defaultCountryCode = '+47' + function PhoneNumber(props: Props) { const sharedContext = useContext(SharedContext) const tr = sharedContext?.translation.Forms + const lang = sharedContext.locale?.split('-')[0] const errorMessages = useMemo( () => ({ @@ -40,9 +45,6 @@ function PhoneNumber(props: Props) { ) const defaultProps: Partial = { - // Important for the default value to be defined here, and not after the useDataValue call, to avoid the UI jumping - // back to +47 once the user empty the field so handleChange send out undefined. - value: '+47', errorMessages, } const preparedProps: Props = { @@ -58,7 +60,6 @@ function PhoneNumber(props: Props) { placeholder, countryCodeLabel, label = sharedContext?.translation.Forms.phoneNumberLabel, - value, numberMask, emptyValue, info, @@ -74,61 +75,116 @@ function PhoneNumber(props: Props) { handleFocus, handleBlur, handleChange, + updateValue, onCountryCodeChange, onNumberChange, } = useDataValue(preparedProps) - const [, countryCode, phoneNumber] = - value !== undefined - ? value.match(/^(\+[^ ]+)? ?(.*)$/) - : [undefined, '', ''] + const countryCodeRef = React.useRef(null) + const phoneNumberRef = React.useRef(null) + const dataRef = React.useRef(null) + const langRef = React.useRef(lang) + + /** + * We do not process the whole country list at the first render. + * Only when the Autocomplete opens (focus). + * To achieve this, we use memo instead of effect to update refs in sync. + * + * We set or update the data list depending on if the countrycode changes or lang changes. + * We then update countryCode and phoneNumber when value changes. + */ + useMemo(() => { + const [countryCode, phoneNumber] = splitValue(props.value) + phoneNumberRef.current = phoneNumber + + if ( + !countryCodeRef.current || + (countryCode && countryCode !== countryCodeRef.current) + ) { + countryCodeRef.current = countryCode || defaultCountryCode + + dataRef.current = getCountryData({ + lang, + filter: countryCodeRef.current, + }) + } - const singleCountryCodeData = useMemo(() => { - return getCountryData({ - lang: sharedContext.locale?.split('-')[0], - filter: countryCode, - }) - }, []) + if (lang !== langRef.current) { + langRef.current = lang + dataRef.current = getCountryData({ + lang, + }) + } + }, [props.value, lang]) + + /** + * On external value change, update the internal, + * only so onFocus and onBlur does have correct (eventually empty) value. + */ + useEffect(() => { + const [countryCode, phoneNumber] = splitValue(props.value) + const newValue = phoneNumber + ? joinValue([countryCode, phoneNumber]) + : emptyValue + updateValue(newValue) + }, [props.value, emptyValue, updateValue]) const handleCountryCodeChange = useCallback( ({ data }: { data: { selectedKey: string } }) => { - const countryCode = data?.selectedKey?.trim() ?? emptyValue + const countryCode = data?.selectedKey?.trim() || emptyValue + const phoneNumber = phoneNumberRef.current || emptyValue + countryCodeRef.current = countryCode - if (!countryCode && !phoneNumber) { - handleChange?.(emptyValue) - onCountryCodeChange?.(emptyValue) - return - } + /** + * To ensure, we actually call onChange every time, + * even if the value is undefined + */ + updateValue('invalidate') + + handleChange( + phoneNumber ? joinValue([countryCode, phoneNumber]) : emptyValue, + { + countryCode, + phoneNumber, + } + ) - handleChange?.([countryCode, phoneNumber].filter(Boolean).join(' ')) onCountryCodeChange?.(countryCode) }, - [phoneNumber, emptyValue, handleChange, onCountryCodeChange] + [emptyValue, updateValue, handleChange, onCountryCodeChange] ) const handleNumberChange = useCallback( - (phoneNumber: string) => { - if (!countryCode && !phoneNumber) { - handleChange?.(emptyValue) - onNumberChange?.(emptyValue) - return - } + (value: string) => { + const phoneNumber = value || emptyValue + const countryCode = countryCodeRef.current || emptyValue + phoneNumberRef.current = phoneNumber || emptyValue + + handleChange( + phoneNumber ? joinValue([countryCode, phoneNumber]) : emptyValue, + { + countryCode, + phoneNumber, + } + ) - handleChange?.([countryCode, phoneNumber].filter(Boolean).join(' ')) onNumberChange?.(phoneNumber) }, - [countryCode, emptyValue, handleChange, onNumberChange] + [emptyValue, handleChange, onNumberChange] ) - const onFocusHandler = ({ dataList, updateData }) => { - // because there can be more than one country with same cdc - if (dataList.length < 10) { - updateData( - getCountryData({ lang: sharedContext.locale?.split('-')[0] }) - ) - } - handleFocus() - } + const onFocusHandler = useCallback( + ({ updateData }) => { + if (dataRef.current.length < 10) { + dataRef.current = getCountryData({ + lang, + }) + updateData(dataRef.current) + } + handleFocus() + }, + [handleFocus, lang] + ) return ( @@ -192,7 +248,7 @@ function PhoneNumber(props: Props) { onFocus={handleFocus} onBlur={handleBlur} onChange={handleNumberChange} - value={phoneNumber} + value={phoneNumberRef.current} info={info} warning={warning} error={error} @@ -232,5 +288,17 @@ function getCountryData({ lang = 'en', filter = null } = {}) { .map((country) => makeObject(country, lang)) } +function splitValue(value: string) { + return ( + typeof value === 'string' + ? value.match(/^(\+[^ ]+)? ?(.*)$/) + : [undefined, '', ''] + ).slice(1) +} + +function joinValue(array: Array) { + return array.filter(Boolean).join(' ') +} + PhoneNumber._supportsSpacingProps = true export default PhoneNumber diff --git a/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/__tests__/PhoneNumber.test.tsx b/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/__tests__/PhoneNumber.test.tsx index 04bc75a2fc3..cfccdfcbb7b 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/__tests__/PhoneNumber.test.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/__tests__/PhoneNumber.test.tsx @@ -40,8 +40,8 @@ describe('Field.PhoneNumber', () => { }) it('should change locale', () => { - render( - + const { rerender } = render( + ) @@ -52,11 +52,32 @@ describe('Field.PhoneNumber', () => { fireEvent.mouseDown(codeElement) - const selectedItemElement = document.querySelector( - '.dnb-drawer-list__option.dnb-drawer-list__option--selected' + const selectedItemElement = () => + document.querySelector( + '.dnb-drawer-list__option.dnb-drawer-list__option--selected' + ) + + expect(selectedItemElement().textContent).toBe('+47 Norge') + + rerender( + + + ) - expect(selectedItemElement.textContent).toBe('+47 Norway') + fireEvent.mouseDown(codeElement) + + expect(selectedItemElement().textContent).toBe('+47 Norway') + + rerender( + + + + ) + + fireEvent.mouseDown(codeElement) + + expect(selectedItemElement().textContent).toBe('+47 Norge') }) it('should return correct value onFocus and onBlur event', async () => { @@ -69,10 +90,10 @@ describe('Field.PhoneNumber', () => { ) fireEvent.focus(phoneElement) - expect(onFocus).toHaveBeenLastCalledWith('+47') + expect(onFocus).toHaveBeenLastCalledWith(undefined) fireEvent.blur(phoneElement) - expect(onBlur).toHaveBeenLastCalledWith('+47') + expect(onBlur).toHaveBeenLastCalledWith(undefined) await userEvent.type(phoneElement, '99999999') @@ -102,9 +123,86 @@ describe('Field.PhoneNumber', () => { expect(item.textContent).toBe('+47 Norge') }) + it('should update internal state from outside', () => { + const onChange = jest.fn() + const onFocus = jest.fn() + const onCountryCodeChange = jest.fn() + + const MockPhoneNumber = () => { + const [state, update] = React.useState('+47 1') + React.useEffect(() => { + update('+41 2') + }, []) + + return ( + { + update(value) + onChange(value) + }} + noAnimation + /> + ) + } + + render() + + const codeElement: HTMLInputElement = document.querySelector( + '.dnb-forms-field-phone-number__country-code input' + ) + const phoneElement: HTMLInputElement = document.querySelector( + '.dnb-forms-field-phone-number__number input' + ) + const firstItemElement = () => + document.querySelectorAll('li.dnb-drawer-list__option')[0] + + expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('2​ ​​ ​​ ​​') + + // Change PhoneNumber + fireEvent.change(phoneElement, { target: { value: '234' } }) + fireEvent.focus(phoneElement) + + expect(onChange).toHaveBeenNthCalledWith(1, '+41 234') + expect(onFocus).toHaveBeenNthCalledWith(1, '+41 234') + expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('23 4​ ​​ ​​') + + // Change CountryCode + fireEvent.focus(codeElement) + fireEvent.keyDown(codeElement, { + key: 'Enter', + keyCode: 13, + }) + fireEvent.change(codeElement, { target: { value: '+47' } }) + fireEvent.click(firstItemElement()) + + expect(onChange).toHaveBeenNthCalledWith(2, '+47 234') + expect(onFocus).toHaveBeenNthCalledWith(2, '+41 234') + expect(onCountryCodeChange).toHaveBeenCalledWith('+47') + expect(codeElement.value).toEqual('NO (+47)') + expect(phoneElement.value).toEqual('23 4​ ​​ ​​') + + fireEvent.focus(phoneElement) + expect(onFocus).toHaveBeenNthCalledWith(3, '+47 234') + + // Empty PhoneNumber – expect empty value + fireEvent.change(phoneElement, { target: { value: '' } }) + fireEvent.focus(phoneElement) + + expect(onChange).toHaveBeenNthCalledWith(3, undefined) + expect(onFocus).toHaveBeenNthCalledWith(4, undefined) + expect(codeElement.value).toEqual('NO (+47)') + expect(phoneElement.value).toEqual('') + }) + it('should return correct value onChange event', async () => { const onChange = jest.fn() const onCountryCodeChange = jest.fn() + render( { /> ) - const phoneElement = document.querySelector( + const phoneElement: HTMLInputElement = document.querySelector( '.dnb-forms-field-phone-number__number input' ) - await userEvent.type(phoneElement, '99999999') - expect(onChange).toHaveBeenLastCalledWith('+47 99999999') - const codeElement: HTMLInputElement = document.querySelector( '.dnb-forms-field-phone-number__country-code input' ) + const firstItemElement = () => + document.querySelectorAll('li.dnb-drawer-list__option')[0] + + await userEvent.type(phoneElement, '99999999') + expect(onChange).toHaveBeenLastCalledWith('+47 99999999', { + countryCode: '+47', + phoneNumber: '99999999', + }) expect(codeElement.value).toEqual('NO (+47)') + expect(phoneElement.value).toEqual('99 99 99 99') // open fireEvent.focus(codeElement) @@ -139,26 +243,136 @@ describe('Field.PhoneNumber', () => { await userEvent.type(codeElement, '{Backspace}') + expect(firstItemElement().textContent).toBe('+47 Norge') expect(codeElement.value).toEqual('NO (+47') + expect(phoneElement.value).toEqual('99 99 99 99') - expect( + fireEvent.change(codeElement, { target: { value: '+41' } }) + fireEvent.click(firstItemElement()) + + await wait(1) + + expect(onCountryCodeChange).toHaveBeenCalledTimes(1) + expect(onCountryCodeChange).toHaveBeenLastCalledWith('+41') + expect(onChange).toHaveBeenLastCalledWith('+41 99999999', { + countryCode: '+41', + phoneNumber: '99999999', + }) + expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('99 99 99 99') + + await userEvent.type(phoneElement, '{Backspace>8}') + + expect(onChange).toHaveBeenLastCalledWith(undefined, { + countryCode: '+41', + phoneNumber: undefined, + }) + }) + + it('should handle events correctly with initial value', async () => { + const onChange = jest.fn() + const onCountryCodeChange = jest.fn() + + render( + + ) + + const codeElement: HTMLInputElement = document.querySelector( + '.dnb-forms-field-phone-number__country-code input' + ) + const phoneElement: HTMLInputElement = document.querySelector( + '.dnb-forms-field-phone-number__number input' + ) + const firstItemElement = () => document.querySelectorAll('li.dnb-drawer-list__option')[0] - .textContent - ).toBe('+47 Norge') + + fireEvent.change(phoneElement, { target: { value: '1' } }) + + expect(onChange).toHaveBeenLastCalledWith('+47 1', { + countryCode: '+47', + phoneNumber: '1', + }) + + fireEvent.change(phoneElement, { target: { value: '' } }) + + expect(onChange).toHaveBeenLastCalledWith(undefined, { + countryCode: '+47', + phoneNumber: undefined, + }) + expect(codeElement.value).toEqual('NO (+47)') + expect(phoneElement.value).toEqual('') fireEvent.focus(codeElement) + fireEvent.keyDown(codeElement, { + key: 'Enter', + keyCode: 13, + }) fireEvent.change(codeElement, { target: { value: '+41' } }) - fireEvent.click( - document.querySelectorAll('li.dnb-drawer-list__option')[0] - ) + fireEvent.click(firstItemElement()) + + expect(onChange).toHaveBeenCalledTimes(3) + expect(onCountryCodeChange).toHaveBeenLastCalledWith('+41') expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('') - await wait(1) + await userEvent.type(phoneElement, '456') + + expect(onChange).toHaveBeenLastCalledWith('+41 456', { + countryCode: '+41', + phoneNumber: '456', + }) + expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('45 6​ ​​ ​​') + }) + + it('should handle events correctly', async () => { + const onChange = jest.fn() + const onCountryCodeChange = jest.fn() + + render( + + ) + + const codeElement: HTMLInputElement = document.querySelector( + '.dnb-forms-field-phone-number__country-code input' + ) + const phoneElement: HTMLInputElement = document.querySelector( + '.dnb-forms-field-phone-number__number input' + ) + const firstItemElement = () => + document.querySelectorAll('li.dnb-drawer-list__option')[0] + + fireEvent.focus(codeElement) + fireEvent.keyDown(codeElement, { + key: 'Enter', + keyCode: 13, + }) + fireEvent.change(codeElement, { target: { value: '+41' } }) + fireEvent.click(firstItemElement()) + + expect(onChange).toHaveBeenCalledTimes(1) - expect(onCountryCodeChange).toHaveBeenCalledTimes(1) expect(onCountryCodeChange).toHaveBeenLastCalledWith('+41') - expect(onChange).toHaveBeenLastCalledWith('+41 99999999') + expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('') + + await userEvent.type(phoneElement, '456') + + expect(onChange).toHaveBeenLastCalledWith('+41 456', { + countryCode: '+41', + phoneNumber: '456', + }) + expect(codeElement.value).toEqual('CH (+41)') + expect(phoneElement.value).toEqual('45 6​ ​​ ​​') }) it('should support spacing props', () => { @@ -182,17 +396,17 @@ describe('Field.PhoneNumber', () => { it('should require one number', async () => { render() - const inputElement = document.querySelector( + const phoneElement = document.querySelector( '.dnb-forms-field-phone-number__number input' - ) as HTMLInputElement + ) - await userEvent.type(inputElement, '1{Backspace}') - fireEvent.blur(inputElement) + await userEvent.type(phoneElement, '1{Backspace}') + fireEvent.blur(phoneElement) expect(document.querySelector('[role="alert"]')).toBeInTheDocument() - await userEvent.type(inputElement, '1') - fireEvent.blur(inputElement) + await userEvent.type(phoneElement, '1') + fireEvent.blur(phoneElement) expect( document.querySelector('[role="alert"]') diff --git a/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/stories/PhoneNumber.stories.tsx b/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/stories/PhoneNumber.stories.tsx index d20c417ae12..7de6051cec7 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/stories/PhoneNumber.stories.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Field/PhoneNumber/stories/PhoneNumber.stories.tsx @@ -1,14 +1,27 @@ -import { Field, Form } from '../../..' +import React from 'react' +import { Field } from '../../..' export default { title: 'Eufemia/Forms/PhoneNumber', } export function PhoneNumber() { + const [state, update] = React.useState('+47 1') + // const [state, update] = React.useState(undefined) + React.useEffect(() => { + // update('+41 1') + update('+45') + }, []) return ( - - - - + { + console.log('onChange', value) + update(value) + }} + /> ) } diff --git a/packages/dnb-eufemia/src/extensions/forms/hooks/useDataValue.ts b/packages/dnb-eufemia/src/extensions/forms/hooks/useDataValue.ts index 57ca863901d..650868c7236 100644 --- a/packages/dnb-eufemia/src/extensions/forms/hooks/useDataValue.ts +++ b/packages/dnb-eufemia/src/extensions/forms/hooks/useDataValue.ts @@ -10,7 +10,7 @@ import pointer from 'json-pointer' import { ValidateFunction } from 'ajv' import { errorChanged } from '../utils' import ajv, { ajvErrorsToOneFormError } from '../utils/ajv' -import { FormError, FieldProps } from '../types' +import { FormError, FieldProps, AdditionalEventArgs } from '../types' import { Context } from '../DataContext' import FieldBlockContext from '../FieldBlock/FieldBlockContext' import IterateElementContext from '../Iterate/IterateElementContext' @@ -420,7 +420,10 @@ export default function useDataValue< ) const handleChange = useCallback( - (argFromInput: Value) => { + ( + argFromInput: Value, + additionalArgs: AdditionalEventArgs = undefined + ) => { const newValue = fromInput(argFromInput) if (newValue === valueRef.current) { @@ -432,7 +435,12 @@ export default function useDataValue< updateValue(newValue) changedRef.current = true - onChange?.(newValue) + onChange?.apply( + this, + typeof additionalArgs !== 'undefined' + ? [newValue, additionalArgs] + : [newValue] + ) if (elementPath) { const iterateValuePath = `/${iterateElementIndex}${ diff --git a/packages/dnb-eufemia/src/extensions/forms/types.ts b/packages/dnb-eufemia/src/extensions/forms/types.ts index 96631086f2a..5332804a150 100644 --- a/packages/dnb-eufemia/src/extensions/forms/types.ts +++ b/packages/dnb-eufemia/src/extensions/forms/types.ts @@ -77,7 +77,10 @@ export interface DataValueWriteProps< emptyValue?: EmptyValue onFocus?: (value: Value | EmptyValue) => void onBlur?: (value: Value | EmptyValue) => void - onChange?: (value: Value | EmptyValue) => void + onChange?: ( + value: Value | EmptyValue, + additionalArgs?: AdditionalEventArgs + ) => void } const dataValueWriteProps = ['emptyValue', 'onFocus', 'onBlur', 'onChange'] @@ -137,6 +140,8 @@ export type ComponentProps = SpacingProps & { className?: string } +export type AdditionalEventArgs = Record + export type DataValueReadComponentProps = ComponentProps & DataValueReadProps