Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Forms): add transformLabel to Value.Composition #4207

Merged
merged 1 commit into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,22 @@ describe('Value.Composition', () => {
document.querySelector('.dnb-forms-value-block__label strong')
).toBeInTheDocument()
})

describe('transformLabel', () => {
it('renders labels', async () => {
render(
<Value.Composition
label="Label"
transformLabel={(label: string) => label.toUpperCase()}
>
<Value.String path="/foo" />
<Value.String path="/bar" />
</Value.Composition>
)

const label = document.querySelector('.dnb-form-label')

expect(label.textContent).toBe('LABEL')
})
})
})
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { PropertiesTableProps } from '../../../../shared/types'
import { ValueProperties } from '../ValueDocs'

const { transformLabel } = ValueProperties

export const SummaryListProperties: PropertiesTableProps = {
layout: {
doc: 'Use `grid`, `horizontal` or `vertical`.',
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',
Expand All @@ -21,6 +19,7 @@ export const SummaryListProperties: PropertiesTableProps = {
type: 'boolean',
status: 'optional',
},
transformLabel,
children: {
doc: 'Contents.',
type: 'React.Node',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<HTMLElement>(null)
useNotInSummaryList(valueBlockContext?.composition ? null : ref, label)
Expand Down Expand Up @@ -205,3 +210,7 @@ function useNotInSummaryList(

ValueBlock._supportsSpacingProps = true
export default ValueBlock

const transformLabelParameters = {
convertJsxToString,
} as unknown as Parameters<Props['transformLabel']>[1]
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -274,4 +274,98 @@ describe('ValueBlock', () => {

log.mockRestore()
})

describe('transformLabel', () => {
it('should transform label', () => {
const transformLabel = jest.fn((label) => label.toUpperCase())
render(
<ValueBlock
label="The label"
transformLabel={transformLabel}
showEmpty
/>
)
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(
<Form.Handler>
<Value.String
label="The label"
transformLabel={transformLabel}
showEmpty
/>
</Form.Handler>
)
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(
<Form.Handler>
<Value.String
label={<span>The label</span>}
transformLabel={transformLabel}
showEmpty
/>
</Form.Handler>
)
expect(transformLabel).toHaveBeenCalledTimes(1)
expect(transformLabel).toHaveBeenLastCalledWith(
<span>The label</span>,
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(
<Form.Handler>
<Value.Provider transformLabel={transformLabel}>
<Value.SummaryList>
<Value.String label="The label A" showEmpty />
<Value.String label="The label B" showEmpty />
</Value.SummaryList>
</Value.Provider>
</Form.Handler>
)

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()
)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -663,99 +663,4 @@ describe('useValueProps', () => {
}
})
})

describe('transformLabel', () => {
it('should transform label', () => {
const transformLabel = jest.fn((label) => label.toUpperCase())
render(
<Form.Handler>
<Value.String
label="The label"
transformLabel={transformLabel}
showEmpty
/>
</Form.Handler>
)
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(
<Form.Handler>
<Value.String
label={<span>The label</span>}
transformLabel={transformLabel}
showEmpty
/>
</Form.Handler>
)
expect(transformLabel).toHaveBeenCalledTimes(1)
expect(transformLabel).toHaveBeenLastCalledWith(
<span>The label</span>,
expect.anything()
)
expect(
document.querySelector('.dnb-forms-value-string')
).toHaveTextContent('THE LABEL')
})

it('should transform label using inheritLabel', () => {
render(
<Form.Handler>
<Field.String path="/myPath" label="The label" />
<Value.String
path="/myPath"
inheritLabel
transformLabel={(label: string) => label.toUpperCase()}
showEmpty
/>
</Form.Handler>
)
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(
<Form.Handler>
<Value.Provider transformLabel={transformLabel}>
<Value.SummaryList>
<Value.String label="The label A" showEmpty />
<Value.String label="The label B" showEmpty />
</Value.SummaryList>
</Value.Provider>
</Form.Handler>
)

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()
)
})
})
})
12 changes: 2 additions & 10 deletions packages/dnb-eufemia/src/extensions/forms/hooks/useValueProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,13 @@ 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'
import ValueProviderContext from '../Value/Provider/ValueProviderContext'

export type Props<Value> = ValueProps<Value>

const transformLabelParameters = {
convertJsxToString,
} as unknown as Parameters<Props<unknown>['transformLabel']>[1]

export default function useValueProps<
Value = unknown,
Props extends ValueProps<Value> = ValueProps<Value>,
Expand All @@ -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,
Expand Down Expand Up @@ -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 }
}
Loading