Skip to content
Open
5 changes: 5 additions & 0 deletions .changeset/wild-parents-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cube-dev/ui-kit': minor
---

Form logic internal fixes.
2 changes: 1 addition & 1 deletion src/components/content/Tag/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const TagElement = tasty({
closable: '0 (2.5x - 1bw) 0 (1x - 1bw)',
},
fill: {
'': '#dark.04',
'': '#light',
...Object.keys(THEMES).reduce((map, type) => {
map[`[data-type="${type}"]`] = THEMES[type].fill;

Expand Down
24 changes: 19 additions & 5 deletions src/components/fields/Checkbox/checkbox-group.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { act, render, renderWithForm, userEvent } from '../../../test';
import { render, renderWithForm, userEvent } from '../../../test';
import { Field, Checkbox } from '../../../index';

jest.mock('../../../_internal/hooks/use-warn');
Expand All @@ -20,17 +20,24 @@ describe('<CheckboxGroup />', () => {

it('should work with new <Form />', async () => {
const { formInstance, getAllByRole } = renderWithForm(
<Checkbox.Group defaultValue={['one']} label="test" name="test">
<Checkbox.Group label="test" name="test">
<Checkbox value="one">One</Checkbox>
<Checkbox value="two">Two</Checkbox>
</Checkbox.Group>,
{
formProps: {
defaultValues: {
test: ['one'],
},
},
},
);
const checkbox = getAllByRole('checkbox');

expect(checkbox[0]).toBeChecked();
expect(checkbox[1]).not.toBeChecked();

await act(async () => await userEvent.click(checkbox[1]));
await userEvent.click(checkbox[1]);

expect(checkbox[0]).toBeChecked();
expect(checkbox[1]).toBeChecked();
Expand All @@ -40,17 +47,24 @@ describe('<CheckboxGroup />', () => {

it('should interop with <Form />', async () => {
const { getAllByRole, formInstance } = renderWithForm(
<Field name="test" defaultValue={['two']}>
<Field name="test">
<Checkbox.Group label="test">
<Checkbox value="one">Buy milk</Checkbox>
<Checkbox value="two">Buy coffee</Checkbox>
<Checkbox value="three">Buy bread</Checkbox>
</Checkbox.Group>
</Field>,
{
formProps: {
defaultValues: {
test: ['two'],
},
},
},
);

const checkbox = getAllByRole('checkbox');
await act(async () => await userEvent.click(checkbox[0]));
await userEvent.click(checkbox[0]);

expect(checkbox[0]).toBeChecked();
expect(checkbox[1]).toBeChecked();
Expand Down
8 changes: 4 additions & 4 deletions src/components/fields/Checkbox/checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import userEvent from '@testing-library/user-event';

import { act, render, renderWithForm } from '../../../test';
import { render, renderWithForm } from '../../../test';
import { Field } from '../../form';

import { Checkbox } from './Checkbox';
Expand All @@ -12,7 +12,7 @@ describe('<Checkbox />', () => {
const { getByRole } = render(<Checkbox>Test</Checkbox>);
const checkboxElement = getByRole('checkbox');

await act(async () => await userEvent.click(checkboxElement));
await userEvent.click(checkboxElement);

expect(checkboxElement).toBeChecked();
});
Expand All @@ -24,7 +24,7 @@ describe('<Checkbox />', () => {

const checkboxElement = getByRole('checkbox');

await act(async () => await userEvent.click(checkboxElement));
await userEvent.click(checkboxElement);

expect(checkboxElement).toBeChecked();
expect(formInstance.getFieldValue('test')).toBe(true);
Expand All @@ -39,7 +39,7 @@ describe('<Checkbox />', () => {

const checkboxElement = getByRole('checkbox');

await act(async () => await userEvent.click(checkboxElement));
await userEvent.click(checkboxElement);

expect(checkboxElement).toBeChecked();
expect(formInstance.getFieldValue('test')).toBe(true);
Expand Down
23 changes: 23 additions & 0 deletions src/components/fields/ComboBox/ComboBox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { userEvent, within } from '@storybook/test';

import { SELECTED_KEY_ARG } from '../../../stories/FormFieldArgs';
import { baseProps } from '../../../stories/lists/baseProps';
import { Form, useForm } from '../../form/index';

import { ComboBox, CubeComboBoxProps } from './ComboBox';

Expand Down Expand Up @@ -32,6 +33,26 @@ const Template: StoryFn<CubeComboBoxProps<any>> = (
</>
);

const FormTemplate: StoryFn<CubeComboBoxProps<any>> = (
args: CubeComboBoxProps<any>,
) => {
const [form] = useForm();

return (
<Form form={form}>
<ComboBox name="combobox" {...args}>
<ComboBox.Item key="red">Red</ComboBox.Item>
<ComboBox.Item key="orange">Orange</ComboBox.Item>
<ComboBox.Item key="yellow">Yellow</ComboBox.Item>
<ComboBox.Item key="green">Green</ComboBox.Item>
<ComboBox.Item key="blue">Blue</ComboBox.Item>
<ComboBox.Item key="purple">Purple</ComboBox.Item>
<ComboBox.Item key="violet">Violet</ComboBox.Item>
</ComboBox>
</Form>
);
};

export const Default = Template.bind({});
Default.args = {};

Expand Down Expand Up @@ -101,3 +122,5 @@ With1LongOptionFiltered.play = async ({ canvasElement }) => {

await userEvent.type(combobox, 'Red');
};

export const WithinForm = FormTemplate.bind({});
10 changes: 9 additions & 1 deletion src/components/fields/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ReactElement,
RefObject,
useMemo,
useState,
} from 'react';
import {
useButton,
Expand Down Expand Up @@ -133,12 +134,19 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
props: CubeComboBoxProps<T>,
ref: ForwardedRef<HTMLDivElement>,
) {
const [rerender, setRerender] = useState({});

props = useProviderProps(props);
props = useFormProps(props);
props = useFieldProps(props, {
valuePropsMapper: ({ value, onChange }) => ({
inputValue: value != null ? value : '',
onInputChange: (val) => onChange(val, !props.allowsCustomValue),
onInputChange: (val) => {
onChange(val, !props.allowsCustomValue);
if (rerender) {
setRerender({});
}
},
onSelectionChange: onChange,
}),
});
Expand Down
2 changes: 2 additions & 0 deletions src/components/fields/RadioGroup/Radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ export interface CubeRadioProps
inputStyles?: Styles;
/* The visual type of the radio button */
type?: 'button' | 'radio';
value?: string;
onChange?: (value: string) => void;
}

function Radio(props: CubeRadioProps, ref) {
Expand Down
5 changes: 2 additions & 3 deletions src/components/fields/RadioGroup/radio.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
act,
renderWithForm,
renderWithRoot,
screen,
Expand All @@ -19,7 +18,7 @@ describe('<Radio /> and <RadioGroup />', () => {
</Radio.Group>,
);
const radio = getAllByRole('radio');
await act(async () => await userEvent.click(radio[0]));
await userEvent.click(radio[0]);

expect(radio[0]).toBeChecked();
});
Expand All @@ -33,7 +32,7 @@ describe('<Radio /> and <RadioGroup />', () => {
);
const radio = screen.getAllByRole('radio');

await act(async () => await userEvent.click(radio[0]));
await userEvent.click(radio[0]);

expect(radio[0]).toBeChecked();

Expand Down
19 changes: 7 additions & 12 deletions src/components/fields/Select/select.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
act,
renderWithForm,
renderWithRoot,
userEvent,
} from '../../../test/index';
import { renderWithForm, renderWithRoot, userEvent } from '../../../test';
import { Field } from '../../form';

import { Select } from './Select';
Expand All @@ -21,10 +16,10 @@ describe('<Select />', () => {
);

const select = getByRole('button');
await act(async () => await userEvent.click(select));
await userEvent.click(select);

const options = getAllByRole('option');
await act(async () => await userEvent.click(options[1]));
await userEvent.click(options[1]);

expect(select).toHaveTextContent('Red');
});
Expand All @@ -41,10 +36,10 @@ describe('<Select />', () => {
);

const select = getByRole('button');
await act(async () => await userEvent.click(select));
await userEvent.click(select);

const options = getAllByRole('option');
await act(async () => await userEvent.click(options[1]));
await userEvent.click(options[1]);

expect(select).toHaveTextContent('Red');
expect(formInstance.getFieldValue('test')).toBe('2');
Expand All @@ -60,10 +55,10 @@ describe('<Select />', () => {
);

const select = getByRole('button');
await act(async () => await userEvent.click(select));
await userEvent.click(select);

const options = getAllByRole('option');
await act(async () => await userEvent.click(options[1]));
await userEvent.click(options[1]);

expect(select).toHaveTextContent('Red');
expect(formInstance.getFieldValue('test')).toBe('2');
Expand Down
8 changes: 4 additions & 4 deletions src/components/fields/Switch/switch.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { renderWithForm, userEvent, render, act } from '../../../test';
import { renderWithForm, userEvent, render } from '../../../test';
import { Field, Switch } from '../../../index';

jest.mock('../../../_internal/hooks/use-warn');
Expand All @@ -8,7 +8,7 @@ describe('<Switch />', () => {
const { getByRole } = render(<Switch aria-label="test" />);
const switchElement = getByRole('switch');

await act(async () => await userEvent.click(switchElement));
await userEvent.click(switchElement);

expect(switchElement).toBeChecked();
});
Expand All @@ -22,7 +22,7 @@ describe('<Switch />', () => {

const switchElement = getByRole('switch');

await act(async () => await userEvent.click(switchElement));
await userEvent.click(switchElement);

expect(switchElement).toBeChecked();
expect(formInstance.getFieldValue('test')).toBe(true);
Expand All @@ -35,7 +35,7 @@ describe('<Switch />', () => {

const switchElement = getByRole('switch');

await act(async () => await userEvent.click(switchElement));
await userEvent.click(switchElement);

expect(switchElement).toBeChecked();
expect(formInstance.getFieldValue('test')).toBe(true);
Expand Down
14 changes: 6 additions & 8 deletions src/components/form/Form/ComplexForm.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,11 @@ const Template: StoryFn<typeof Form> = (args) => {
<Field label="Custom field" tooltip="What?">
<Block>Test</Block>
</Field>
<Field
<TextInput
name="email"
label="Email field"
type="email"
size="small"
rules={[
{ required: true, message: 'This field is required' },
{
Expand All @@ -269,13 +272,8 @@ const Template: StoryFn<typeof Form> = (args) => {
},
]}
necessityIndicator={'label'}
defaultValue="[email protected]"
shouldUpdate={({ email }) => {
return !!email;
}}
>
<TextInput type="email" size="small" label="Email field" />
</Field>
shouldUpdate={(prevValues, { email }) => !!email}
/>
<Field name="password">
<PasswordInput label="Password field" />
</Field>
Expand Down
Loading
Loading