Skip to content

Commit

Permalink
release of v10.49 (#3940)
Browse files Browse the repository at this point in the history
  • Loading branch information
langz authored Sep 16, 2024
2 parents e949422 + 0f9dff3 commit fe11b58
Show file tree
Hide file tree
Showing 36 changed files with 560 additions and 212 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ export const InitialOpen = () => {
<Flex.Stack>
<Form.MainHeading>Statsborgerskap</Form.MainHeading>

<Card align="stretch">
<Card stack>
<Iterate.Array path="/countries" defaultValue={[null]}>
<Iterate.ViewContainer toolbarVariant="minimumOneItem">
<Value.SelectCountry
Expand Down Expand Up @@ -455,6 +455,7 @@ export const WithArrayValidator = () => {
return new Error('You need at least two items')
}
}}
animate
>
<Flex.Horizontal align="flex-end">
<Field.String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,40 @@ hideInMenu: true
import { Iterate, Field } from '@dnb/eufemia/extensions/forms'

render(
<>
<Iterate.Array path="/">
<Form.Handler>
<Iterate.Array path="/myList">
<Field.Name.Last itemPath="/name" />
</Iterate.Array>

<Iterate.PushButton text="Add another item" path="/" pushValue={{}} />
</>,
<Iterate.PushButton
path="/myList"
text="Add another item"
pushValue={{}}
/>
</Form.Handler>,
)
```

In order to create new items you can also use the [Iterate.PushContainer](/uilib/extensions/forms/Iterate/PushContainer/) component.

## Show the next item number in the button

You can use the `{nextItemNo}` variable in the `text` or `children` property to display the next item number.

```tsx
import { Iterate, Field, Value } from '@dnb/eufemia/extensions/forms'

render(
<Form.Handler>
<Iterate.Array path="/myList">
<Field.String itemPath="/" />
</Iterate.Array>

<Iterate.PushButton
path="/myList"
pushValue="push value"
text="Add no. {nextItemNo}"
/>
</Form.Handler>,
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ You can place it below the [Array](/uilib/extensions/forms/Iterate/Array/) compo
import { Iterate, Field } from '@dnb/eufemia/extensions/forms'

render(
<>
<Iterate.Array>...</Iterate.Array>
<Form.Handler>
<Iterate.Array path="/myList">...</Iterate.Array>

<Iterate.PushContainer title="New item title">
<Iterate.PushContainer path="/myList" title="New item title">
<Field.Name.Last itemPath="/name" />
</Iterate.PushContainer>
</>,
</Form.Handler>,
)
```

Expand All @@ -41,10 +41,11 @@ The button will be shown instead of the content provided by the children when th
import { Iterate, Field } from '@dnb/eufemia/extensions/forms'

render(
<>
<Iterate.Array>...</Iterate.Array>
<Form.Handler>
<Iterate.Array path="/myList">...</Iterate.Array>

<Iterate.PushContainer
path="/myList"
title="New item title"
openButton={
<Iterate.PushContainer.OpenButton text="Add another item" />
Expand All @@ -53,8 +54,33 @@ render(
>
Will be hidden based on the showOpenButtonWhen function
</Iterate.PushContainer>
</>,
</Form.Handler>,
)
```

The `Iterate.PushContainer.OpenButton` accepts the same props as the [Button](/uilib/components/button/) component.

## Show the next item number in the open button

You can use the `{nextItemNo}` variable in the `text` or `children` property to display the next item number.

```tsx
import { Iterate, Field, Value } from '@dnb/eufemia/extensions/forms'

render(
<Form.Handler>
<Iterate.Array path="/myList">...</Iterate.Array>

<Iterate.PushContainer
path="/myList"
title="New item title"
openButton={
<Iterate.PushContainer.OpenButton text="Add no. {nextItemNo}" />
}
showOpenButtonWhen={(list) => list.length > 0}
>
<Field.Name.Last itemPath="/name" />
</Iterate.PushContainer>
</Form.Handler>,
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ You can also prevent the user from navigating to the next or previous step, by u
import { Form, Wizard } from '@dnb/eufemia/extensions/forms'

const MyForm = () => {
const { setActiveIndex, activeIndex } = Wizard.useStep('unique-id')

return (
<Form.Handler>
<Wizard.Container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ breadcrumb:

import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { ChildrenWithAgeProperties } from '@dnb/eufemia/src/extensions/forms/blocks/ChildrenWithAge/ChildrenWithAgeDocs'
import { ChildrenWithAge, ChildrenWithAgeWizard } from './Examples'
import * as Examples from './Examples'

# ChildrenWithAge

Expand All @@ -29,20 +29,26 @@ render(<ChildrenWithAge />)

All features are enabled in this example.

<ChildrenWithAgeWizard />
<Examples.ChildrenWithAgeWizard />

## Basic

<ChildrenWithAge />
<Examples.ChildrenWithAge />

## With `joint-responsibility` question

<ChildrenWithAge enableAdditionalQuestions={['joint-responsibility']} />
<Examples.ChildrenWithAge
enableAdditionalQuestions={['joint-responsibility']}
/>

## With `daycare` question

<ChildrenWithAge enableAdditionalQuestions={['daycare']} />
<Examples.ChildrenWithAge enableAdditionalQuestions={['daycare']} />

## Properties

<PropertiesTable props={ChildrenWithAgeProperties} />

<VisibleWhenVisualTest>
<Examples.ChildrenWithAgePrefilledYes />
</VisibleWhenVisualTest>
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const ChildrenWithAge = (props) => {
</Form.Handler>
)
}

export const ChildrenWithAgeWizard = (props) => {
return (
<ComponentBox scope={{ Blocks, props }}>
Expand Down Expand Up @@ -160,3 +161,28 @@ function Output({ title, generateRef, transform = (data) => data }) {
</>
)
}

export const ChildrenWithAgePrefilledYes = (props) => {
return (
<ComponentBox
data-visual-test="children-with-age-prefilled"
scope={{ Blocks }}
>
<Form.Handler
data={{
hasChildren: true,
hasJointResponsibility: true,
usesDaycare: true,
countChildren: 2,
children: [{}, {}],
}}
>
<Flex.Stack>
<Blocks.ChildrenWithAge
enableAdditionalQuestions={['joint-responsibility', 'daycare']}
/>
</Flex.Stack>
</Form.Handler>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default class HeightAnimation {
this.callAnimationEnd()
}
getHeight() {
return parseFloat(String(this.elem?.clientHeight)) || null
return this.withFallback(this.elem, 'clientHeight') ?? null
}
getUnknownHeight() {
if (!this.elem) {
Expand Down Expand Up @@ -198,20 +198,15 @@ export default class HeightAnimation {
// so we need to set the width to the original width
const elemWidth = this.elem.clientWidth
const clonedWidth =
clonedElem.clientWidth ||
// data-width is used for mockup testing with "mockHeight"
parseFloat(clonedElem.getAttribute('data-width')) ||
0
this.withFallback(clonedElem, 'clientWidth', 'data-width') ?? 0

if (clonedWidth > elemWidth) {
clonedElem.style.width = `${elemWidth}px`
}

const height =
clonedElem.clientHeight ||
// data-height is used for mockup testing with "mockHeight"
parseFloat(clonedElem.getAttribute('data-height')) ||
null
this.withFallback(this.elem, 'clientHeight', 'data-height') ?? null

clonedElem.parentNode?.removeChild(clonedElem)

Expand All @@ -221,6 +216,22 @@ export default class HeightAnimation {

return height
}
withFallback(
elem: HTMLElement,
key: 'clientHeight' | 'clientWidth',
fallback?: 'data-height' | 'data-width'
) {
const val =
fallback && elem.hasAttribute(fallback)
? parseFloat(elem.getAttribute(fallback))
: elem?.[key]

if (isNaN(val)) {
return null
}

return val
}
onStart(fn: HeightAnimationOnStartCallback) {
this.onStartStack.push(fn)
}
Expand Down Expand Up @@ -348,7 +359,7 @@ export default class HeightAnimation {
return
}

if (fromHeight === 0 || fromHeight === null) {
if (fromHeight === null) {
fromHeight = this.getHeight()
}
if (toHeight === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ describe('HeightAnimationInstance', () => {
expect(inst.getHeight()).toBe(100)
})

it('getHeight with 0 should return 0', () => {
const inst = new HeightAnimationInstance()
inst.setElement(element)

mockHeight(0, element)

expect(inst.getHeight()).toBe(0)
})

it('getHeight with unknown value should return "null"', () => {
const inst = new HeightAnimationInstance()
inst.setElement(element)

mockHeight(undefined, element)

expect(inst.getHeight()).toBe(null)
})

describe('getUnknownHeight', () => {
it('should return proper height', () => {
const inst = new HeightAnimationInstance()
Expand Down
14 changes: 8 additions & 6 deletions packages/dnb-eufemia/src/extensions/forms/DataContext/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ type HandleSubmitProps = {
formElement?: HTMLFormElement
}

export type MountOptions = {
isMounted?: boolean
}

export type EventListenerCall = {
path?: Path
type?: 'onSubmit' | 'onPathChange'
Expand Down Expand Up @@ -93,8 +97,7 @@ export interface ContextState {
hasFieldError: (path: Path) => boolean
setFieldState: (path: Path, fieldState: SubmitState) => void
setFieldError: (path: Path, error: Error | FormError) => void
handleMountField: (path: Path) => void
handleUnMountField: (path: Path) => void
setMountedFieldState: (path: Path, options: MountOptions) => void
setFormState?: (state: SubmitState) => void
setSubmitState?: (state: EventStateObject) => void
addOnChangeHandler?: (callback: OnChange) => void
Expand All @@ -117,13 +120,13 @@ export interface ContextState {
type: EventListenerCall['type'],
callback: EventListenerCall['callback']
) => void
setHasVisibleError?: (path: Path, hasError: boolean) => void
setVisibleError?: (path: Path, hasError: boolean) => void
setFieldProps?: (path: Path, props: unknown) => void
setValueProps?: (path: Path, props: unknown) => void
setHandleSubmit?: (callback: HandleSubmitCallback) => void
fieldPropsRef?: React.MutableRefObject<Record<string, FieldProps>>
valuePropsRef?: React.MutableRefObject<Record<string, ValueProps>>
mountedFieldPathsRef?: React.MutableRefObject<Path[]>
mountedFieldsRef?: React.MutableRefObject<Record<Path, MountOptions>>
showAllErrors: boolean
hasVisibleError: boolean
formState: SubmitState
Expand Down Expand Up @@ -158,8 +161,7 @@ export const defaultContextState: ContextState = {
setSubmitState: () => null,
handleSubmitCall: () => null,
setShowAllErrors: () => null,
handleMountField: () => null,
handleUnMountField: () => null,
setMountedFieldState: () => null,
hasErrors: () => false,
hasFieldState: () => false,
hasFieldError: () => false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ export interface FieldBoundaryContextState {
* To set the local error state.
*/
setFieldError?: (path: Path, error: Error) => void

/**
* To set the local visible error state.
*/
setVisibleError?: (path: Path, hasError: boolean) => void
}

const FieldBoundaryContext = React.createContext<
Expand Down
Loading

0 comments on commit fe11b58

Please sign in to comment.