From 45120590e8f4ca37833315cf6582c476b036df55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20H=C3=B8egh?= Date: Fri, 1 Nov 2024 18:07:30 +0100 Subject: [PATCH] feat(Forms): add `transformLabel` to Value.Composition --- .../Value/Composition/CompositionDocs.ts | 3 +- .../__tests__/Composition.test.tsx | 18 ++++ .../Value/SummaryList/SummaryListDocs.ts | 9 +- .../forms/ValueBlock/ValueBlock.tsx | 15 ++- .../ValueBlock/__tests__/ValueBlock.test.tsx | 96 ++++++++++++++++++- .../hooks/__tests__/useValueProps.test.tsx | 95 ------------------ .../extensions/forms/hooks/useValueProps.ts | 12 +-- 7 files changed, 133 insertions(+), 115 deletions(-) diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/Composition/CompositionDocs.ts b/packages/dnb-eufemia/src/extensions/forms/Value/Composition/CompositionDocs.ts index 7e32eb14d3b..2ac5e88e840 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Value/Composition/CompositionDocs.ts +++ b/packages/dnb-eufemia/src/extensions/forms/Value/Composition/CompositionDocs.ts @@ -1,10 +1,11 @@ import { PropertiesTableProps } from '../../../../shared/types' import { ValueProperties } from '../ValueDocs' -const { label } = ValueProperties +const { label, transformLabel } = ValueProperties export const CompositionProperties: PropertiesTableProps = { label, + transformLabel, maxWidth: { doc: 'Use `small`, `medium` or `large` for predefined standard max widths. Defaults to `auto`.', type: 'string', diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/Composition/__tests__/Composition.test.tsx b/packages/dnb-eufemia/src/extensions/forms/Value/Composition/__tests__/Composition.test.tsx index b4a715e9b98..36bd01d1020 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Value/Composition/__tests__/Composition.test.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Value/Composition/__tests__/Composition.test.tsx @@ -217,4 +217,22 @@ describe('Value.Composition', () => { document.querySelector('.dnb-forms-value-block__label strong') ).toBeInTheDocument() }) + + describe('transformLabel', () => { + it('renders labels', async () => { + render( + label.toUpperCase()} + > + + + + ) + + const label = document.querySelector('.dnb-form-label') + + expect(label.textContent).toBe('LABEL') + }) + }) }) diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/SummaryList/SummaryListDocs.ts b/packages/dnb-eufemia/src/extensions/forms/Value/SummaryList/SummaryListDocs.ts index 14d90f78fc6..7434545cd3a 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Value/SummaryList/SummaryListDocs.ts +++ b/packages/dnb-eufemia/src/extensions/forms/Value/SummaryList/SummaryListDocs.ts @@ -1,4 +1,7 @@ import { PropertiesTableProps } from '../../../../shared/types' +import { ValueProperties } from '../ValueDocs' + +const { transformLabel } = ValueProperties export const SummaryListProperties: PropertiesTableProps = { layout: { @@ -6,11 +9,6 @@ export const SummaryListProperties: PropertiesTableProps = { type: 'string', status: 'optional', }, - transformLabel: { - doc: 'Transforms the label before it gets displayed. Receives the label as the first parameter. The second parameter is a object containing the `convertJsxToString` function.', - type: 'function', - status: 'optional', - }, inheritVisibility: { doc: 'Use this property to propagate the `inheritVisibility` property to all nested values.', type: 'boolean', @@ -21,6 +19,7 @@ export const SummaryListProperties: PropertiesTableProps = { type: 'boolean', status: 'optional', }, + transformLabel, children: { doc: 'Contents.', type: 'React.Node', diff --git a/packages/dnb-eufemia/src/extensions/forms/ValueBlock/ValueBlock.tsx b/packages/dnb-eufemia/src/extensions/forms/ValueBlock/ValueBlock.tsx index 9a16ca6bb74..b057b0f58aa 100644 --- a/packages/dnb-eufemia/src/extensions/forms/ValueBlock/ValueBlock.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/ValueBlock/ValueBlock.tsx @@ -43,6 +43,7 @@ function ValueBlock(props: Props) { const { className, label: labelProp, + transformLabel = (label: Props['label']) => label, inline, maxWidth = props.composition ? props.maxWidth : 'large', placeholder, @@ -56,14 +57,18 @@ function ValueBlock(props: Props) { if (inline) { return null } + + let label = labelProp + if (iterateIndex !== undefined) { - return convertJsxToString(labelProp).replace( + label = convertJsxToString(labelProp).replace( '{itemNo}', String(iterateIndex + 1) ) } - return labelProp - }, [inline, iterateIndex, labelProp]) + + return transformLabel(label, transformLabelParameters) + }, [inline, iterateIndex, labelProp, transformLabel]) const ref = useRef(null) useNotInSummaryList(valueBlockContext?.composition ? null : ref, label) @@ -205,3 +210,7 @@ function useNotInSummaryList( ValueBlock._supportsSpacingProps = true export default ValueBlock + +const transformLabelParameters = { + convertJsxToString, +} as unknown as Parameters[1] diff --git a/packages/dnb-eufemia/src/extensions/forms/ValueBlock/__tests__/ValueBlock.test.tsx b/packages/dnb-eufemia/src/extensions/forms/ValueBlock/__tests__/ValueBlock.test.tsx index 9fb5c92d8f0..ccb04c3bb22 100644 --- a/packages/dnb-eufemia/src/extensions/forms/ValueBlock/__tests__/ValueBlock.test.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/ValueBlock/__tests__/ValueBlock.test.tsx @@ -2,7 +2,7 @@ import React from 'react' import { axeComponent } from '../../../../core/jest/jestSetup' import { render } from '@testing-library/react' import ValueBlock from '../ValueBlock' -import { Value } from '../..' +import { Form, Value } from '../..' describe('ValueBlock', () => { it('renders without crashing', () => { @@ -274,4 +274,98 @@ describe('ValueBlock', () => { log.mockRestore() }) + + describe('transformLabel', () => { + it('should transform label', () => { + const transformLabel = jest.fn((label) => label.toUpperCase()) + render( + + ) + expect(transformLabel).toHaveBeenCalledTimes(1) + expect(transformLabel).toHaveBeenLastCalledWith( + 'The label', + expect.anything() + ) + expect(document.querySelector('.dnb-form-label')).toHaveTextContent( + 'THE LABEL' + ) + }) + + it('should transform label in Value.String', () => { + const transformLabel = jest.fn((label) => label.toUpperCase()) + render( + + + + ) + expect(transformLabel).toHaveBeenCalledTimes(1) + expect(transformLabel).toHaveBeenLastCalledWith( + 'The label', + expect.anything() + ) + expect( + document.querySelector('.dnb-forms-value-string') + ).toHaveTextContent('THE LABEL') + }) + + it('should transform a JSX label and return "convertJsxToString"', () => { + const transformLabel = jest.fn((label, { convertJsxToString }) => + convertJsxToString(label).toUpperCase() + ) + render( + + The label} + transformLabel={transformLabel} + showEmpty + /> + + ) + expect(transformLabel).toHaveBeenCalledTimes(1) + expect(transformLabel).toHaveBeenLastCalledWith( + The label, + expect.anything() + ) + expect( + document.querySelector('.dnb-forms-value-string') + ).toHaveTextContent('THE LABEL') + }) + + it('should transform label using Value.Provider', () => { + const transformLabel = jest.fn((label) => label.toUpperCase()) + render( + + + + + + + + + ) + + const [first, second] = Array.from(document.querySelectorAll('dt')) + expect(first).toHaveTextContent('THE LABEL A') + expect(second).toHaveTextContent('THE LABEL B') + expect(transformLabel).toHaveBeenCalledTimes(2) + expect(transformLabel).toHaveBeenNthCalledWith( + 1, + 'The label A', + expect.anything() + ) + expect(transformLabel).toHaveBeenNthCalledWith( + 2, + 'The label B', + expect.anything() + ) + }) + }) }) diff --git a/packages/dnb-eufemia/src/extensions/forms/hooks/__tests__/useValueProps.test.tsx b/packages/dnb-eufemia/src/extensions/forms/hooks/__tests__/useValueProps.test.tsx index b93b31f2224..b4a69b54cfc 100644 --- a/packages/dnb-eufemia/src/extensions/forms/hooks/__tests__/useValueProps.test.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/hooks/__tests__/useValueProps.test.tsx @@ -663,99 +663,4 @@ describe('useValueProps', () => { } }) }) - - describe('transformLabel', () => { - it('should transform label', () => { - const transformLabel = jest.fn((label) => label.toUpperCase()) - render( - - - - ) - expect(transformLabel).toHaveBeenCalledTimes(1) - expect(transformLabel).toHaveBeenLastCalledWith( - 'The label', - expect.anything() - ) - expect( - document.querySelector('.dnb-forms-value-string') - ).toHaveTextContent('THE LABEL') - }) - - it('should transform a JSX label and return "convertJsxToString"', () => { - const transformLabel = jest.fn((label, { convertJsxToString }) => - convertJsxToString(label).toUpperCase() - ) - render( - - The label} - transformLabel={transformLabel} - showEmpty - /> - - ) - expect(transformLabel).toHaveBeenCalledTimes(1) - expect(transformLabel).toHaveBeenLastCalledWith( - The label, - expect.anything() - ) - expect( - document.querySelector('.dnb-forms-value-string') - ).toHaveTextContent('THE LABEL') - }) - - it('should transform label using inheritLabel', () => { - render( - - - label.toUpperCase()} - showEmpty - /> - - ) - expect( - document.querySelector('.dnb-forms-field-string') - ).toHaveTextContent('The label') - expect( - document.querySelector('.dnb-forms-value-string') - ).toHaveTextContent('THE LABEL') - }) - - it('should transform label using Value.Provider', () => { - const transformLabel = jest.fn((label) => label.toUpperCase()) - render( - - - - - - - - - ) - - const [first, second] = Array.from(document.querySelectorAll('dt')) - expect(first).toHaveTextContent('THE LABEL A') - expect(second).toHaveTextContent('THE LABEL B') - expect(transformLabel).toHaveBeenCalledTimes(2) - expect(transformLabel).toHaveBeenNthCalledWith( - 1, - 'The label A', - expect.anything() - ) - expect(transformLabel).toHaveBeenNthCalledWith( - 2, - 'The label B', - expect.anything() - ) - }) - }) }) diff --git a/packages/dnb-eufemia/src/extensions/forms/hooks/useValueProps.ts b/packages/dnb-eufemia/src/extensions/forms/hooks/useValueProps.ts index 65fd847eb38..873bc37cac0 100644 --- a/packages/dnb-eufemia/src/extensions/forms/hooks/useValueProps.ts +++ b/packages/dnb-eufemia/src/extensions/forms/hooks/useValueProps.ts @@ -6,7 +6,6 @@ import { useRef, } from 'react' import { Path, ValueProps } from '../types' -import { convertJsxToString } from '../../../shared/component-helper' import useExternalValue from './useExternalValue' import usePath from './usePath' import DataContext from '../DataContext/Context' @@ -14,10 +13,6 @@ import ValueProviderContext from '../Value/Provider/ValueProviderContext' export type Props = ValueProps -const transformLabelParameters = { - convertJsxToString, -} as unknown as Parameters['transformLabel']>[1] - export default function useValueProps< Value = unknown, Props extends ValueProps = ValueProps, @@ -34,7 +29,6 @@ export default function useValueProps< defaultValue, inheritVisibility, inheritLabel, - transformLabel = (label: Props['label']) => label, transformIn = (value: Value) => value, toInput = (value: Value) => value, fromExternal = (value: Value) => value, @@ -93,11 +87,9 @@ export default function useValueProps< ? transformIn(toInput(externalValue)) : undefined - const label = transformLabel( + const label = props.label ?? - (inheritLabel ? fieldPropsRef?.current?.[path]?.label : undefined), - transformLabelParameters - ) + (inheritLabel ? fieldPropsRef?.current?.[path]?.label : undefined) return { ...props, label, value } }