Skip to content

Commit d31976e

Browse files
authored
refactor(Field): complete migration to wrapWithField wrapper (#425)
1 parent 3ffc1b5 commit d31976e

File tree

11 files changed

+103
-150
lines changed

11 files changed

+103
-150
lines changed

.changeset/friendly-books-compare.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@cube-dev/ui-kit': minor
3+
---
4+
5+
Add casting property to Field component to cast Field value to different type that input allows

src/components/forms/FileInput/FileInput.tsx

+11-27
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
tasty,
2323
} from '../../../tasty';
2424
import { FieldBaseProps } from '../../../shared';
25-
import { FieldWrapper } from '../FieldWrapper';
25+
import { wrapWithField } from '../wrapper';
2626

2727
import type { AriaTextFieldProps } from '@react-types/textfield';
2828

@@ -135,6 +135,8 @@ function extractContents(element, callback) {
135135
}
136136

137137
function FileInput(props: CubeFileInputProps, ref) {
138+
props = useProviderProps(props);
139+
138140
let {
139141
id,
140142
name,
@@ -163,11 +165,14 @@ function FileInput(props: CubeFileInputProps, ref) {
163165
type = 'file',
164166
inputProps,
165167
...otherProps
166-
} = useProviderProps(props);
168+
} = props;
169+
167170
const [value, setValue] = useState();
168171
const [dragHover, setDragHover] = useState(false);
172+
169173
let domRef = useRef(null);
170174
let defaultInputRef = useRef(null);
175+
171176
inputRef = inputRef || defaultInputRef;
172177

173178
let styles = extractStyles(otherProps, CONTAINER_STYLES);
@@ -247,31 +252,10 @@ function FileInput(props: CubeFileInputProps, ref) {
247252
</FileInputElement>
248253
);
249254

250-
return (
251-
<FieldWrapper
252-
{...{
253-
labelPosition,
254-
label,
255-
extra,
256-
styles,
257-
isRequired,
258-
labelStyles,
259-
necessityIndicator,
260-
necessityLabel,
261-
labelProps,
262-
isDisabled,
263-
validationState,
264-
message,
265-
description,
266-
requiredMark,
267-
tooltip,
268-
isHidden,
269-
labelSuffix,
270-
Component: fileInput,
271-
ref: domRef,
272-
}}
273-
/>
274-
);
255+
return wrapWithField(fileInput, domRef, {
256+
...props,
257+
styles,
258+
});
275259
}
276260

277261
/**

src/components/forms/Form/ComplexForm.stories.tsx

+39-39
Original file line numberDiff line numberDiff line change
@@ -36,43 +36,43 @@ export default {
3636
parameters: { controls: { exclude: baseProps } },
3737
};
3838

39-
const UnknownSubmitErrorTemplate: StoryFn<typeof Form> = (args) => {
40-
const [form] = Form.useForm();
41-
42-
return (
43-
<Form
44-
form={form}
45-
{...args}
46-
onSubmit={(v) => {
47-
console.log('onSubmit:', v);
48-
49-
throw new Error('Unknown error');
50-
}}
51-
onSubmitFailed={(e) => {
52-
console.log('onSubmitFailed', e);
53-
}}
54-
onValuesChange={(v) => {
55-
console.log('onChange', v);
56-
}}
57-
>
58-
<Field
59-
name="text"
60-
label="Text input"
61-
rules={[
62-
() => ({
63-
async validator() {
64-
await timeout(1000);
65-
},
66-
}),
67-
]}
68-
>
69-
<TextInput />
70-
</Field>
71-
<Submit>Submit</Submit>
72-
<SubmitError />
73-
</Form>
74-
);
75-
};
39+
// const UnknownSubmitErrorTemplate: StoryFn<typeof Form> = (args) => {
40+
// const [form] = Form.useForm();
41+
//
42+
// return (
43+
// <Form
44+
// form={form}
45+
// {...args}
46+
// onSubmit={(v) => {
47+
// console.log('onSubmit:', v);
48+
//
49+
// throw new Error('Unknown error');
50+
// }}
51+
// onSubmitFailed={(e) => {
52+
// console.log('onSubmitFailed', e);
53+
// }}
54+
// onValuesChange={(v) => {
55+
// console.log('onChange', v);
56+
// }}
57+
// >
58+
// <Field
59+
// name="text"
60+
// label="Text input"
61+
// rules={[
62+
// () => ({
63+
// async validator() {
64+
// await timeout(1000);
65+
// },
66+
// }),
67+
// ]}
68+
// >
69+
// <TextInput />
70+
// </Field>
71+
// <Submit>Submit</Submit>
72+
// <SubmitError />
73+
// </Form>
74+
// );
75+
// };
7676

7777
const CustomSubmitErrorTemplate: StoryFn<typeof Form> = (args) => {
7878
const [form] = Form.useForm();
@@ -387,8 +387,8 @@ ErrorMessage.play = CustomErrorMessage.play = async ({ canvasElement }) => {
387387
await waitFor(() => expect(canvas.getByRole('alert')).toBeInTheDocument());
388388
};
389389

390-
export const UnknownErrorMessage = UnknownSubmitErrorTemplate.bind({});
391-
390+
// export const UnknownErrorMessage = UnknownSubmitErrorTemplate.bind({});
391+
//
392392
// UnknownErrorMessage.play = async ({ canvasElement }) => {
393393
// const canvas = within(canvasElement);
394394
// const button = await canvas.getByRole('button');

src/components/forms/Form/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type CubeFieldData<Name extends string, Value> = {
88
readonly name: Name;
99
errors: ReactNode[];
1010
value?: Value;
11-
inputValue?: Value;
11+
inputValue?: Value | string | undefined | null;
1212
touched?: boolean;
1313
rules?: any[];
1414
validating?: boolean;

src/components/forms/Form/use-field/use-field-props.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ export function useFieldProps<
7777
// eslint-disable-next-line react-hooks/rules-of-hooks
7878
const onBlurChained = useChainedCallback(
7979
field?.onBlur,
80-
// TODO: remove type casting after updating to typescipt@4.9
8180
'onBlur' in props ? (props as any).onBlur : undefined,
8281
);
8382

src/components/forms/Form/use-field/use-field.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,13 @@ export function useField<T extends FieldTypes, Props extends CubeFieldProps<T>>(
172172
}
173173
});
174174

175+
let inputValue = field?.inputValue;
176+
175177
return useMemo(
176178
() => ({
177179
id: fieldId,
178180
name: fieldName,
179-
value: field?.inputValue,
181+
value: inputValue,
180182
validateTrigger,
181183
form,
182184
field,

src/components/forms/Slider/SliderBase.tsx

+12-21
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import { FocusableRef } from '@react-types/shared';
44
import { SliderState, useSliderState } from 'react-stately';
55
import { useSlider, useNumberFormatter } from 'react-aria';
66

7-
import { FieldWrapper } from '../FieldWrapper';
87
import { extractStyles, OUTER_STYLES, tasty } from '../../../tasty';
98
import { useFieldProps, useFormProps } from '../Form';
109
import { Text } from '../../content/Text';
10+
import { mergeProps } from '../../../utils/react';
11+
import { wrapWithField } from '../wrapper';
1112

1213
import { SliderControlsElement, SliderElement } from './elements';
1314
import { CubeSliderBaseProps } from './types';
@@ -211,27 +212,17 @@ function SliderBase(
211212

212213
styles = extractStyles(otherProps, OUTER_STYLES, styles);
213214

214-
return (
215-
<FieldWrapper
216-
{...{
217-
labelPosition,
218-
label,
219-
extra,
215+
return wrapWithField(
216+
sliderField,
217+
ref,
218+
mergeProps(
219+
{
220+
...props,
220221
styles,
221-
isRequired,
222-
labelStyles,
223-
necessityIndicator,
224-
labelProps,
225-
isDisabled,
226-
validationState,
227-
message,
228-
description,
229-
requiredMark,
230-
labelSuffix,
231-
Component: sliderField,
232-
ref: ref,
233-
}}
234-
/>
222+
extra,
223+
},
224+
{ labelProps },
225+
),
235226
);
236227
}
237228

src/components/forms/wrapper.tsx

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ReactElement, RefObject } from 'react';
2+
import { FocusableRef } from '@react-types/shared';
23

34
import { FieldBaseProps, FormBaseProps } from '../../shared';
45
import { BaseProps, Styles } from '../../tasty';
@@ -11,7 +12,7 @@ interface WrapWithFieldProps extends FieldBaseProps, BaseProps, FormBaseProps {
1112

1213
export function wrapWithField<T extends WrapWithFieldProps>(
1314
component: ReactElement,
14-
ref: RefObject<unknown>,
15+
ref: RefObject<unknown> | FocusableRef<HTMLElement>,
1516
props: T,
1617
) {
1718
let {
@@ -20,13 +21,14 @@ export function wrapWithField<T extends WrapWithFieldProps>(
2021
labelPosition = 'top',
2122
labelStyles,
2223
isRequired,
24+
isDisabled,
2325
necessityIndicator,
24-
necessityLabel,
25-
validationState,
2626
message,
27+
messageStyles,
2728
description,
28-
isDisabled,
29+
validationState,
2930
labelProps,
31+
fieldProps,
3032
requiredMark = true,
3133
tooltip,
3234
isHidden,
@@ -38,23 +40,24 @@ export function wrapWithField<T extends WrapWithFieldProps>(
3840
return (
3941
<FieldWrapper
4042
{...{
41-
labelPosition,
4243
label,
4344
extra,
44-
styles,
45-
isRequired,
45+
labelPosition,
4646
labelStyles,
47+
isRequired,
48+
isDisabled,
4749
necessityIndicator,
48-
necessityLabel,
4950
labelProps,
50-
isDisabled,
51-
validationState,
51+
fieldProps,
5252
message,
53+
messageStyles,
5354
description,
55+
validationState,
5456
requiredMark,
5557
tooltip,
5658
isHidden,
5759
labelSuffix,
60+
styles,
5861
children,
5962
Component: component,
6063
ref,

src/components/pickers/ComboBox/ComboBox.tsx

+6-25
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ import {
3030
useCombinedRefs,
3131
useLayoutEffect,
3232
} from '../../../utils/react';
33-
import { FieldWrapper } from '../../forms/FieldWrapper';
3433
import { CubeSelectBaseProps, ListBoxPopup } from '../Select/Select';
3534
import { DEFAULT_INPUT_STYLES, INPUT_WRAPPER_STYLES } from '../../forms';
3635
import { OverlayWrapper } from '../../overlays/OverlayWrapper';
36+
import { wrapWithField } from '../../forms/wrapper';
3737
import { LoadingIcon } from '../../../icons';
3838
import { InvalidIcon } from '../../shared/InvalidIcon';
3939
import { ValidIcon } from '../../shared/ValidIcon';
@@ -143,7 +143,6 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
143143
qa,
144144
label,
145145
extra,
146-
labelPosition = 'top',
147146
labelStyles,
148147
isRequired,
149148
necessityIndicator,
@@ -174,7 +173,6 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
174173
autoComplete = 'off',
175174
direction = 'bottom',
176175
shouldFlip = true,
177-
requiredMark = true,
178176
menuTrigger = 'input',
179177
suffixPosition = 'before',
180178
loadingState,
@@ -400,31 +398,14 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
400398
</ComboBoxWrapperElement>
401399
);
402400

403-
return (
404-
<FieldWrapper
405-
{...{
406-
labelPosition,
407-
label,
408-
extra,
409-
styles,
410-
isRequired,
411-
labelStyles,
412-
necessityIndicator,
413-
labelProps,
414-
isDisabled,
415-
validationState,
416-
message,
417-
description,
418-
requiredMark,
419-
labelSuffix,
420-
Component: comboBoxField,
421-
ref: ref,
422-
}}
423-
/>
401+
return wrapWithField<Omit<CubeComboBoxProps<T>, 'children'>>(
402+
comboBoxField,
403+
ref,
404+
mergeProps({ ...props, styles }, { labelProps }),
424405
);
425406
}) as unknown as (<T>(
426407
props: CubeComboBoxProps<T> & { ref?: ForwardedRef<HTMLDivElement> },
427-
) => JSX.Element) & { Item: typeof Item };
408+
) => ReactElement) & { Item: typeof Item };
428409

429410
ComboBox.Item = Item;
430411
Object.defineProperty(ComboBox, 'cubeInputType', {

0 commit comments

Comments
 (0)