@ultraviolet/form 3.9.7 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/components/CheckboxField/index.cjs +8 -2
  2. package/dist/components/CheckboxField/index.d.ts +2 -2
  3. package/dist/components/CheckboxField/index.js +8 -2
  4. package/dist/components/CheckboxGroupField/index.d.ts +5 -7
  5. package/dist/components/NumberInputFieldV2/index.cjs +1 -1
  6. package/dist/components/NumberInputFieldV2/index.d.ts +1 -1
  7. package/dist/components/NumberInputFieldV2/index.js +1 -1
  8. package/dist/components/RadioField/index.cjs +17 -2
  9. package/dist/components/RadioField/index.d.ts +3 -3
  10. package/dist/components/RadioField/index.js +17 -2
  11. package/dist/components/RadioGroupField/index.d.ts +1 -7
  12. package/dist/components/SelectInputFieldV2/index.cjs +1 -1
  13. package/dist/components/SelectInputFieldV2/index.js +1 -1
  14. package/dist/components/SelectableCardField/index.cjs +12 -3
  15. package/dist/components/SelectableCardField/index.d.ts +9 -5
  16. package/dist/components/SelectableCardField/index.js +12 -3
  17. package/dist/components/SliderField/index.cjs +3 -2
  18. package/dist/components/SliderField/index.d.ts +1 -1
  19. package/dist/components/SliderField/index.js +3 -2
  20. package/dist/components/TagInputField/index.cjs +3 -2
  21. package/dist/components/TagInputField/index.d.ts +2 -2
  22. package/dist/components/TagInputField/index.js +3 -2
  23. package/dist/components/TextAreaField/index.cjs +1 -1
  24. package/dist/components/TextAreaField/index.js +1 -1
  25. package/dist/components/TextInputFieldV2/index.cjs +1 -1
  26. package/dist/components/TextInputFieldV2/index.js +1 -1
  27. package/dist/components/ToggleField/index.cjs +3 -2
  28. package/dist/components/ToggleField/index.d.ts +2 -2
  29. package/dist/components/ToggleField/index.js +3 -2
  30. package/dist/components/ToggleGroupField/index.d.ts +1 -0
  31. package/dist/components/VerificationCodeField/index.cjs +60 -0
  32. package/dist/components/VerificationCodeField/index.d.ts +12 -0
  33. package/dist/components/VerificationCodeField/index.js +60 -0
  34. package/dist/components/index.d.ts +1 -0
  35. package/dist/index.cjs +2 -0
  36. package/dist/index.js +2 -0
  37. package/dist/types.d.ts +19 -0
  38. package/package.json +3 -3
@@ -15,6 +15,7 @@ const CheckboxField = ({
15
15
  onBlur,
16
16
  shouldUnregister = false,
17
17
  validate,
18
+ "aria-label": ariaLabel,
18
19
  ...props
19
20
  }) => {
20
21
  const {
@@ -42,7 +43,12 @@ const CheckboxField = ({
42
43
  field.onBlur();
43
44
  onBlur?.(event);
44
45
  }, disabled: field.disabled, checked: !!field.value, error: getError({
45
- label: label ?? ""
46
- }, error), ref: field.ref, children });
46
+ label: label ?? ariaLabel ?? name
47
+ }, error), ref: field.ref, ...children ? {
48
+ children,
49
+ "aria-label": void 0
50
+ } : {
51
+ "aria-label": ariaLabel
52
+ } });
47
53
  };
48
54
  exports.CheckboxField = CheckboxField;
@@ -2,9 +2,9 @@ import { Checkbox } from '@ultraviolet/ui';
2
2
  import type { ComponentProps, ReactNode } from 'react';
3
3
  import type { FieldPath, FieldValues } from 'react-hook-form';
4
4
  import type { BaseFieldProps } from '../../types';
5
- type CheckboxFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'value'> & Omit<ComponentProps<typeof Checkbox>, 'value' | 'onChange' | 'aria-label'> & {
5
+ type CheckboxFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'value'> & Omit<ComponentProps<typeof Checkbox>, 'value' | 'onChange'> & {
6
6
  className?: string;
7
7
  children?: ReactNode;
8
8
  };
9
- export declare const CheckboxField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ control, name, label, disabled, required, children, onChange, onBlur, shouldUnregister, validate, ...props }: CheckboxFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
9
+ export declare const CheckboxField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ control, name, label, disabled, required, children, onChange, onBlur, shouldUnregister, validate, "aria-label": ariaLabel, ...props }: CheckboxFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -13,6 +13,7 @@ const CheckboxField = ({
13
13
  onBlur,
14
14
  shouldUnregister = false,
15
15
  validate,
16
+ "aria-label": ariaLabel,
16
17
  ...props
17
18
  }) => {
18
19
  const {
@@ -40,8 +41,13 @@ const CheckboxField = ({
40
41
  field.onBlur();
41
42
  onBlur?.(event);
42
43
  }, disabled: field.disabled, checked: !!field.value, error: getError({
43
- label: label ?? ""
44
- }, error), ref: field.ref, children });
44
+ label: label ?? ariaLabel ?? name
45
+ }, error), ref: field.ref, ...children ? {
46
+ children,
47
+ "aria-label": void 0
48
+ } : {
49
+ "aria-label": ariaLabel
50
+ } });
45
51
  };
46
52
  export {
47
53
  CheckboxField
@@ -17,15 +17,13 @@ export declare const CheckboxGroupField: {
17
17
  required?: boolean;
18
18
  'data-testid'?: string;
19
19
  tooltip?: string;
20
- } & (Pick<import("react").InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "onBlur" | "name" | "onFocus" | "autoFocus" | "id" | "tabIndex"> & (({
21
- "aria-label"?: undefined;
22
- } & {
20
+ } & (Pick<import("react").InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "onBlur" | "name" | "onFocus" | "autoFocus" | "id" | "tabIndex"> & ({
23
21
  children: import("react").ReactNode;
24
- }) | ({
25
- children?: undefined;
26
- } & {
22
+ 'aria-label'?: never;
23
+ } | {
24
+ children?: never;
27
25
  'aria-label': string;
28
- })))) & import("react").RefAttributes<HTMLInputElement>, "onChange" | "checked"> & {
26
+ }))) & import("react").RefAttributes<HTMLInputElement>, "onChange" | "checked"> & {
29
27
  value: string;
30
28
  }) => import("@emotion/react/jsx-runtime").JSX.Element;
31
29
  };
@@ -62,7 +62,7 @@ const NumberInputFieldV2 = ({
62
62
  field.onChange(newValue);
63
63
  onChange?.(newValue);
64
64
  }, max, min, size, step, className, "data-testid": dataTestId, id, label, labelDescription, placeholder, error: getError({
65
- label: label ?? "",
65
+ label: label ?? ariaLabel ?? name,
66
66
  max,
67
67
  min,
68
68
  isInteger: step
@@ -2,7 +2,7 @@ import { NumberInputV2 } from '@ultraviolet/ui';
2
2
  import type { ComponentProps } from 'react';
3
3
  import type { FieldPath, FieldValues } from 'react-hook-form';
4
4
  import type { BaseFieldProps } from '../../types';
5
- type NumberInputV2Props<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = BaseFieldProps<TFieldValues, TFieldName> & Partial<Pick<ComponentProps<typeof NumberInputV2>, 'disabled' | 'id' | 'onBlur' | 'onChange' | 'onFocus' | 'value' | 'data-testid' | 'label' | 'tooltip' | 'unit' | 'size' | 'step' | 'className' | 'placeholder' | 'error' | 'success' | 'helper' | 'labelDescription' | 'aria-label' | 'autoFocus' | 'readOnly' | 'min' | 'max' | 'controls'>> & {
5
+ type NumberInputV2Props<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = BaseFieldProps<TFieldValues, TFieldName> & Partial<Pick<ComponentProps<typeof NumberInputV2>, 'disabled' | 'id' | 'onBlur' | 'onChange' | 'onFocus' | 'value' | 'data-testid' | 'label' | 'aria-label' | 'tooltip' | 'unit' | 'size' | 'step' | 'className' | 'placeholder' | 'error' | 'success' | 'helper' | 'labelDescription' | 'autoFocus' | 'readOnly' | 'min' | 'max' | 'controls'>> & {
6
6
  className?: string;
7
7
  };
8
8
  export declare const NumberInputFieldV2: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ disabled, control, max, min, name, onChange, onBlur, size, step, unit, tooltip, className, label, labelDescription, id, placeholder, success, helper, controls, "aria-label": ariaLabel, "data-testid": dataTestId, required, autoFocus, readOnly, shouldUnregister, validate, }: NumberInputV2Props<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
@@ -60,7 +60,7 @@ const NumberInputFieldV2 = ({
60
60
  field.onChange(newValue);
61
61
  onChange?.(newValue);
62
62
  }, max, min, size, step, className, "data-testid": dataTestId, id, label, labelDescription, placeholder, error: getError({
63
- label: label ?? "",
63
+ label: label ?? ariaLabel ?? name,
64
64
  max,
65
65
  min,
66
66
  isInteger: step
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("@emotion/react/jsx-runtime");
4
4
  const ui = require("@ultraviolet/ui");
5
+ const react = require("react");
5
6
  const reactHookForm = require("react-hook-form");
6
7
  const index = require("../../providers/ErrorContext/index.cjs");
7
8
  const RadioField = ({
@@ -16,6 +17,7 @@ const RadioField = ({
16
17
  value,
17
18
  shouldUnregister = false,
18
19
  validate,
20
+ "aria-label": ariaLabel,
19
21
  ...props
20
22
  }) => {
21
23
  const {
@@ -35,14 +37,27 @@ const RadioField = ({
35
37
  validate
36
38
  }
37
39
  });
40
+ const errorLabel = react.useMemo(() => {
41
+ if (label && typeof label === "string") {
42
+ return label;
43
+ }
44
+ if (ariaLabel) {
45
+ return ariaLabel;
46
+ }
47
+ return name;
48
+ }, [label, name, ariaLabel]);
38
49
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Radio, { ...props, name: field.name, checked: field.value === value, disabled, error: getError({
39
- label: typeof label === "string" ? label : ""
50
+ label: errorLabel
40
51
  }, error), onChange: () => {
41
52
  field.onChange(value);
42
53
  onChange?.(value);
43
54
  }, onBlur: (event) => {
44
55
  field.onBlur();
45
56
  onBlur?.(event);
46
- }, onFocus, required, value: value ?? "", label });
57
+ }, onFocus, required, value: value ?? "", ...label ? {
58
+ label
59
+ } : {
60
+ "aria-label": ariaLabel
61
+ } });
47
62
  };
48
63
  exports.RadioField = RadioField;
@@ -1,10 +1,10 @@
1
1
  import { Radio } from '@ultraviolet/ui';
2
- import type { ComponentProps } from 'react';
2
+ import { type ComponentProps } from 'react';
3
3
  import type { FieldPath, FieldValues } from 'react-hook-form';
4
4
  import type { BaseFieldProps } from '../../types';
5
- type RadioFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'label'> & Omit<ComponentProps<typeof Radio>, 'value' | 'onChange' | 'aria-label'>;
5
+ type RadioFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'label'> & Omit<ComponentProps<typeof Radio>, 'value' | 'onChange'>;
6
6
  /**
7
7
  * @deprecated This component is deprecated, use `RadioGroupField` instead.
8
8
  */
9
- export declare const RadioField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ control, disabled, name, onBlur, label, onChange, onFocus, required, value, shouldUnregister, validate, ...props }: RadioFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
9
+ export declare const RadioField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ control, disabled, name, onBlur, label, onChange, onFocus, required, value, shouldUnregister, validate, "aria-label": ariaLabel, ...props }: RadioFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -1,5 +1,6 @@
1
1
  import { jsx } from "@emotion/react/jsx-runtime";
2
2
  import { Radio } from "@ultraviolet/ui";
3
+ import { useMemo } from "react";
3
4
  import { useController } from "react-hook-form";
4
5
  import { useErrors } from "../../providers/ErrorContext/index.js";
5
6
  const RadioField = ({
@@ -14,6 +15,7 @@ const RadioField = ({
14
15
  value,
15
16
  shouldUnregister = false,
16
17
  validate,
18
+ "aria-label": ariaLabel,
17
19
  ...props
18
20
  }) => {
19
21
  const {
@@ -33,15 +35,28 @@ const RadioField = ({
33
35
  validate
34
36
  }
35
37
  });
38
+ const errorLabel = useMemo(() => {
39
+ if (label && typeof label === "string") {
40
+ return label;
41
+ }
42
+ if (ariaLabel) {
43
+ return ariaLabel;
44
+ }
45
+ return name;
46
+ }, [label, name, ariaLabel]);
36
47
  return /* @__PURE__ */ jsx(Radio, { ...props, name: field.name, checked: field.value === value, disabled, error: getError({
37
- label: typeof label === "string" ? label : ""
48
+ label: errorLabel
38
49
  }, error), onChange: () => {
39
50
  field.onChange(value);
40
51
  onChange?.(value);
41
52
  }, onBlur: (event) => {
42
53
  field.onBlur();
43
54
  onBlur?.(event);
44
- }, onFocus, required, value: value ?? "", label });
55
+ }, onFocus, required, value: value ?? "", ...label ? {
56
+ label
57
+ } : {
58
+ "aria-label": ariaLabel
59
+ } });
45
60
  };
46
61
  export {
47
62
  RadioField
@@ -13,13 +13,7 @@ export declare const RadioGroupField: {
13
13
  className?: string;
14
14
  'data-testid'?: string;
15
15
  tooltip?: string;
16
- } & Required<Pick<import("react").InputHTMLAttributes<HTMLInputElement>, "onChange">> & (Pick<import("react").InputHTMLAttributes<HTMLInputElement>, "required" | "onBlur" | "disabled" | "name" | "onFocus" | "autoFocus" | "id" | "tabIndex" | "onKeyDown"> & ({
17
- 'aria-label': string;
18
- label?: never;
19
- } | {
20
- 'aria-label'?: never;
21
- label: import("react").ReactNode;
22
- }))) & import("react").RefAttributes<HTMLInputElement>, "required" | "onChange" | "checked"> & {
16
+ } & Required<Pick<import("react").InputHTMLAttributes<HTMLInputElement>, "onChange">> & (Pick<import("react").InputHTMLAttributes<HTMLInputElement>, "required" | "onBlur" | "disabled" | "name" | "onFocus" | "autoFocus" | "id" | "tabIndex" | "onKeyDown"> & import("node_modules/@ultraviolet/ui/dist/types").LabelProp)) & import("react").RefAttributes<HTMLInputElement>, "required" | "onChange" | "checked"> & {
23
17
  name?: string;
24
18
  }) => import("@emotion/react/jsx-runtime").JSX.Element;
25
19
  };
@@ -67,7 +67,7 @@ const SelectInputFieldV2 = ({
67
67
  field.onBlur();
68
68
  onBlur?.(event);
69
69
  }, placeholder, readOnly, multiselect, value: field.value, placeholderSearch, helper, emptyState, searchable, clearable, descriptionDirection, footer, labelDescription, error: getError({
70
- label
70
+ label: label ?? ariaLabel ?? name
71
71
  }, error), success, loadMore, isLoading, selectAll, selectAllGroup, autofocus, optionalInfoPlacement, "aria-label": ariaLabel, onChange: handleChange, tooltip });
72
72
  };
73
73
  exports.SelectInputFieldV2 = SelectInputFieldV2;
@@ -65,7 +65,7 @@ const SelectInputFieldV2 = ({
65
65
  field.onBlur();
66
66
  onBlur?.(event);
67
67
  }, placeholder, readOnly, multiselect, value: field.value, placeholderSearch, helper, emptyState, searchable, clearable, descriptionDirection, footer, labelDescription, error: getError({
68
- label
68
+ label: label ?? ariaLabel ?? name
69
69
  }, error), success, loadMore, isLoading, selectAll, selectAllGroup, autofocus, optionalInfoPlacement, "aria-label": ariaLabel, onChange: handleChange, tooltip });
70
70
  };
71
71
  export {
@@ -23,7 +23,8 @@ const SelectableCardField = ({
23
23
  validate,
24
24
  productIcon,
25
25
  illustration,
26
- "data-testid": dataTestId
26
+ "data-testid": dataTestId,
27
+ "aria-label": ariaLabel
27
28
  }) => {
28
29
  const {
29
30
  field,
@@ -40,7 +41,15 @@ const SelectableCardField = ({
40
41
  }
41
42
  });
42
43
  const isChecked = type === "checkbox" && Array.isArray(field.value) && value ? (field.value ?? []).includes(value) : field.value === value;
43
- return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectableCard, { productIcon, illustration, isError: !!error, showTick, checked: isChecked, className, disabled, onChange: (event) => {
44
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectableCard, { ...productIcon ? {
45
+ productIcon
46
+ } : {
47
+ illustration
48
+ }, ...label ? {
49
+ label
50
+ } : {
51
+ "aria-label": ariaLabel
52
+ }, isError: !!error, showTick, checked: isChecked, className, disabled, onChange: (event) => {
44
53
  if (type === "checkbox") {
45
54
  const fieldValue = field.value ?? [];
46
55
  if (fieldValue?.includes(event.currentTarget.value)) {
@@ -57,6 +66,6 @@ const SelectableCardField = ({
57
66
  onBlur?.(event);
58
67
  }, onFocus: (event) => {
59
68
  onFocus?.(event);
60
- }, type, id, tooltip, label, value: value ?? "", name: field.name, "data-testid": dataTestId, children });
69
+ }, type, id, tooltip, value: value ?? "", name: field.name, "data-testid": dataTestId, children });
61
70
  };
62
71
  exports.SelectableCardField = SelectableCardField;
@@ -1,11 +1,15 @@
1
1
  import { SelectableCard } from '@ultraviolet/ui';
2
2
  import type { ComponentProps } from 'react';
3
3
  import type { FieldPath, FieldValues } from 'react-hook-form';
4
- import type { BaseFieldProps } from '../../types';
5
- type SelectableCardFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'label'> & Partial<Pick<ComponentProps<typeof SelectableCard>, 'disabled' | 'onBlur' | 'onFocus' | 'showTick' | 'type' | 'id' | 'children' | 'tooltip' | 'label' | 'data-testid'>> & {
4
+ import type { BaseFieldProps, LabelProp } from '../../types';
5
+ type SelectableCardFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'label'> & Partial<Pick<ComponentProps<typeof SelectableCard>, 'disabled' | 'onBlur' | 'onFocus' | 'showTick' | 'type' | 'id' | 'children' | 'tooltip' | 'data-testid'>> & {
6
6
  className?: string;
7
- illustration?: string;
7
+ } & ({
8
+ illustration?: ComponentProps<typeof SelectableCard>['illustration'];
8
9
  productIcon?: never;
9
- };
10
- export declare const SelectableCardField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, control, value, onChange, showTick, type, disabled, children, className, onFocus, onBlur, required, tooltip, id, label, shouldUnregister, validate, productIcon, illustration, "data-testid": dataTestId, }: SelectableCardFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
10
+ } | {
11
+ productIcon?: ComponentProps<typeof SelectableCard>['productIcon'];
12
+ illustration?: never;
13
+ }) & LabelProp;
14
+ export declare const SelectableCardField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, control, value, onChange, showTick, type, disabled, children, className, onFocus, onBlur, required, tooltip, id, label, shouldUnregister, validate, productIcon, illustration, "data-testid": dataTestId, "aria-label": ariaLabel, }: SelectableCardFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
11
15
  export {};
@@ -21,7 +21,8 @@ const SelectableCardField = ({
21
21
  validate,
22
22
  productIcon,
23
23
  illustration,
24
- "data-testid": dataTestId
24
+ "data-testid": dataTestId,
25
+ "aria-label": ariaLabel
25
26
  }) => {
26
27
  const {
27
28
  field,
@@ -38,7 +39,15 @@ const SelectableCardField = ({
38
39
  }
39
40
  });
40
41
  const isChecked = type === "checkbox" && Array.isArray(field.value) && value ? (field.value ?? []).includes(value) : field.value === value;
41
- return /* @__PURE__ */ jsx(SelectableCard, { productIcon, illustration, isError: !!error, showTick, checked: isChecked, className, disabled, onChange: (event) => {
42
+ return /* @__PURE__ */ jsx(SelectableCard, { ...productIcon ? {
43
+ productIcon
44
+ } : {
45
+ illustration
46
+ }, ...label ? {
47
+ label
48
+ } : {
49
+ "aria-label": ariaLabel
50
+ }, isError: !!error, showTick, checked: isChecked, className, disabled, onChange: (event) => {
42
51
  if (type === "checkbox") {
43
52
  const fieldValue = field.value ?? [];
44
53
  if (fieldValue?.includes(event.currentTarget.value)) {
@@ -55,7 +64,7 @@ const SelectableCardField = ({
55
64
  onBlur?.(event);
56
65
  }, onFocus: (event) => {
57
66
  onFocus?.(event);
58
- }, type, id, tooltip, label, value: value ?? "", name: field.name, "data-testid": dataTestId, children });
67
+ }, type, id, tooltip, value: value ?? "", name: field.name, "data-testid": dataTestId, children });
59
68
  };
60
69
  export {
61
70
  SelectableCardField
@@ -19,6 +19,7 @@ const SliderField = ({
19
19
  value,
20
20
  defaultValue,
21
21
  options,
22
+ "aria-label": ariaLabel,
22
23
  ...props
23
24
  }) => {
24
25
  const {
@@ -66,9 +67,9 @@ const SliderField = ({
66
67
  onChange?.(newValue);
67
68
  }
68
69
  }, max, min, error: getError({
69
- label: label ?? "",
70
+ label: label ?? ariaLabel ?? name,
70
71
  max,
71
72
  min
72
- }, error), label, required, options, ...props });
73
+ }, error), label, required, options, "aria-label": ariaLabel, ...props });
73
74
  };
74
75
  exports.SliderField = SliderField;
@@ -5,5 +5,5 @@ import type { BaseFieldProps } from '../../types';
5
5
  type SliderFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = BaseFieldProps<TFieldValues, TFieldName> & Omit<ComponentProps<typeof Slider>, 'value' | 'onChange'> & {
6
6
  suffix?: string | ReactNode[];
7
7
  };
8
- export declare const SliderField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, control, shouldUnregister, max, min, required, validate, onBlur, onChange, label, value, defaultValue, options, ...props }: SliderFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
8
+ export declare const SliderField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, control, shouldUnregister, max, min, required, validate, onBlur, onChange, label, value, defaultValue, options, "aria-label": ariaLabel, ...props }: SliderFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
9
9
  export {};
@@ -17,6 +17,7 @@ const SliderField = ({
17
17
  value,
18
18
  defaultValue,
19
19
  options,
20
+ "aria-label": ariaLabel,
20
21
  ...props
21
22
  }) => {
22
23
  const {
@@ -64,10 +65,10 @@ const SliderField = ({
64
65
  onChange?.(newValue);
65
66
  }
66
67
  }, max, min, error: getError({
67
- label: label ?? "",
68
+ label: label ?? ariaLabel ?? name,
68
69
  max,
69
70
  min
70
- }, error), label, required, options, ...props });
71
+ }, error), label, required, options, "aria-label": ariaLabel, ...props });
71
72
  };
72
73
  export {
73
74
  SliderField
@@ -25,7 +25,8 @@ const TagInputField = ({
25
25
  success,
26
26
  readOnly,
27
27
  tooltip,
28
- validate
28
+ validate,
29
+ "aria-label": ariaLabel
29
30
  }) => {
30
31
  const {
31
32
  getError
@@ -54,7 +55,7 @@ const TagInputField = ({
54
55
  onChange?.(newTags);
55
56
  }, placeholder, variant, value: field.value, "data-testid": dataTestId, clearable, label, labelDescription, size, success, error: getError({
56
57
  regex: regexes,
57
- label: label ?? ""
58
+ label: label ?? ariaLabel ?? name
58
59
  }, error), readOnly, tooltip });
59
60
  };
60
61
  exports.TagInputField = TagInputField;
@@ -2,7 +2,7 @@ import { TagInput } from '@ultraviolet/ui';
2
2
  import type { ComponentProps } from 'react';
3
3
  import type { FieldPath, FieldValues } from 'react-hook-form';
4
4
  import type { BaseFieldProps } from '../../types';
5
- export type TagInputFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = BaseFieldProps<TFieldValues, TFieldName> & Partial<Pick<ComponentProps<typeof TagInput>, 'variant' | 'placeholder' | 'disabled' | 'className' | 'id' | 'data-testid' | 'clearable' | 'label' | 'labelDescription' | 'size' | 'success' | 'readOnly' | 'tooltip'>> & {
5
+ export type TagInputFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = BaseFieldProps<TFieldValues, TFieldName> & Partial<Pick<ComponentProps<typeof TagInput>, 'variant' | 'placeholder' | 'disabled' | 'className' | 'id' | 'data-testid' | 'clearable' | 'label' | 'labelDescription' | 'size' | 'success' | 'readOnly' | 'tooltip' | 'aria-label'>> & {
6
6
  regex?: (RegExp | RegExp[])[];
7
7
  };
8
- export declare const TagInputField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ regex: regexes, className, disabled, id, control, name, onChange, placeholder, required, variant, shouldUnregister, "data-testid": dataTestId, clearable, label, labelDescription, size, success, readOnly, tooltip, validate, }: TagInputFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
8
+ export declare const TagInputField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ regex: regexes, className, disabled, id, control, name, onChange, placeholder, required, variant, shouldUnregister, "data-testid": dataTestId, clearable, label, labelDescription, size, success, readOnly, tooltip, validate, "aria-label": ariaLabel, }: TagInputFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
@@ -23,7 +23,8 @@ const TagInputField = ({
23
23
  success,
24
24
  readOnly,
25
25
  tooltip,
26
- validate
26
+ validate,
27
+ "aria-label": ariaLabel
27
28
  }) => {
28
29
  const {
29
30
  getError
@@ -52,7 +53,7 @@ const TagInputField = ({
52
53
  onChange?.(newTags);
53
54
  }, placeholder, variant, value: field.value, "data-testid": dataTestId, clearable, label, labelDescription, size, success, error: getError({
54
55
  regex: regexes,
55
- label: label ?? ""
56
+ label: label ?? ariaLabel ?? name
56
57
  }, error), readOnly, tooltip });
57
58
  };
58
59
  export {
@@ -79,7 +79,7 @@ const TextAreaField = ({
79
79
  regex: regexes,
80
80
  minLength,
81
81
  maxLength,
82
- label: label ?? ariaLabel,
82
+ label: label ?? ariaLabel ?? name,
83
83
  value: field.value
84
84
  }, error), helper, labelDescription, minLength, maxLength, name, onBlur: (event) => {
85
85
  onBlur?.(event);
@@ -77,7 +77,7 @@ const TextAreaField = ({
77
77
  regex: regexes,
78
78
  minLength,
79
79
  maxLength,
80
- label: label ?? ariaLabel,
80
+ label: label ?? ariaLabel ?? name,
81
81
  value: field.value
82
82
  }, error), helper, labelDescription, minLength, maxLength, name, onBlur: (event) => {
83
83
  onBlur?.(event);
@@ -72,7 +72,7 @@ const TextInputField = ({
72
72
  regex: regexes,
73
73
  minLength,
74
74
  maxLength,
75
- label: label ?? "",
75
+ label: label ?? ariaLabel ?? name,
76
76
  value: field.value
77
77
  }, error), helper, label, loading, labelDescription, minLength, maxLength, name, onBlur: (event) => {
78
78
  onBlur?.(event);
@@ -70,7 +70,7 @@ const TextInputField = ({
70
70
  regex: regexes,
71
71
  minLength,
72
72
  maxLength,
73
- label: label ?? "",
73
+ label: label ?? ariaLabel ?? name,
74
74
  value: field.value
75
75
  }, error), helper, label, loading, labelDescription, minLength, maxLength, name, onBlur: (event) => {
76
76
  onBlur?.(event);
@@ -19,7 +19,8 @@ const ToggleField = ({
19
19
  format,
20
20
  "data-testid": dataTestId,
21
21
  shouldUnregister = false,
22
- validate
22
+ validate,
23
+ "aria-label": ariaLabel
23
24
  }) => {
24
25
  const {
25
26
  field,
@@ -52,7 +53,7 @@ const ToggleField = ({
52
53
  }
53
54
  onChange?.(event.target.checked);
54
55
  }, label, size, disabled, labelPosition, className, required, "data-testid": dataTestId, error: getError({
55
- label: name
56
+ label: typeof label === "string" ? label : ariaLabel ?? name
56
57
  }, error) });
57
58
  };
58
59
  exports.ToggleField = ToggleField;
@@ -2,9 +2,9 @@ import { Toggle } from '@ultraviolet/ui';
2
2
  import type { ComponentProps } from 'react';
3
3
  import type { FieldPath, FieldValues } from 'react-hook-form';
4
4
  import type { BaseFieldProps } from '../../types';
5
- type ToggleFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'label'> & Pick<ComponentProps<typeof Toggle>, 'disabled' | 'label' | 'size' | 'tooltip' | 'labelPosition' | 'className' | 'data-testid'> & {
5
+ type ToggleFieldProps<TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues>> = Omit<BaseFieldProps<TFieldValues, TFieldName>, 'label'> & Pick<ComponentProps<typeof Toggle>, 'disabled' | 'label' | 'size' | 'tooltip' | 'labelPosition' | 'className' | 'data-testid' | 'aria-label'> & {
6
6
  parse?: (value: boolean) => any;
7
7
  format?: (value: any) => boolean;
8
8
  };
9
- export declare const ToggleField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ className, disabled, label, name, control, onChange, required, size, tooltip, labelPosition, parse, format, "data-testid": dataTestId, shouldUnregister, validate, }: ToggleFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
9
+ export declare const ToggleField: <TFieldValues extends FieldValues, TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ className, disabled, label, name, control, onChange, required, size, tooltip, labelPosition, parse, format, "data-testid": dataTestId, shouldUnregister, validate, "aria-label": ariaLabel, }: ToggleFieldProps<TFieldValues, TFieldName>) => import("@emotion/react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -17,7 +17,8 @@ const ToggleField = ({
17
17
  format,
18
18
  "data-testid": dataTestId,
19
19
  shouldUnregister = false,
20
- validate
20
+ validate,
21
+ "aria-label": ariaLabel
21
22
  }) => {
22
23
  const {
23
24
  field,
@@ -50,7 +51,7 @@ const ToggleField = ({
50
51
  }
51
52
  onChange?.(event.target.checked);
52
53
  }, label, size, disabled, labelPosition, className, required, "data-testid": dataTestId, error: getError({
53
- label: name
54
+ label: typeof label === "string" ? label : ariaLabel ?? name
54
55
  }, error) });
55
56
  };
56
57
  export {
@@ -14,6 +14,7 @@ export declare const ToggleGroupField: {
14
14
  size?: "large" | "small";
15
15
  labelPosition?: "left" | "right";
16
16
  label?: import("react").ReactNode;
17
+ 'aria-label'?: string;
17
18
  helper?: import("react").ReactNode;
18
19
  disabled?: boolean;
19
20
  className?: string;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("@emotion/react/jsx-runtime");
4
+ const ui = require("@ultraviolet/ui");
5
+ const reactHookForm = require("react-hook-form");
6
+ const index = require("../../providers/ErrorContext/index.cjs");
7
+ const VerificationCodeField = ({
8
+ className,
9
+ fields,
10
+ id = "verification-code-input",
11
+ label,
12
+ name,
13
+ onChange,
14
+ onComplete,
15
+ placeholder,
16
+ required,
17
+ type = "number",
18
+ disabled,
19
+ validate
20
+ }) => {
21
+ const {
22
+ getError
23
+ } = index.useErrors();
24
+ const {
25
+ field,
26
+ fieldState: {
27
+ error
28
+ }
29
+ } = reactHookForm.useController({
30
+ name,
31
+ rules: {
32
+ required,
33
+ validate: {
34
+ required: (localValue) => {
35
+ if (required && localValue.length !== (fields ?? 4)) {
36
+ return false;
37
+ }
38
+ return true;
39
+ },
40
+ ...validate
41
+ }
42
+ }
43
+ });
44
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { className, gap: 1, justifyContent: "center", alignItems: "center", direction: "column", "aria-label": "verification-code-field", children: [
45
+ label ? /* @__PURE__ */ jsxRuntime.jsx("label", { id: `${id}-label`, htmlFor: `${id}-0`, style: {
46
+ cursor: "pointer",
47
+ flexShrink: 0
48
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "p", variant: "body", prominence: "strong", children: label }) }) : null,
49
+ /* @__PURE__ */ jsxRuntime.jsx(ui.VerificationCode, { inputId: id, error: !!error, placeholder, fields, onChange: (event) => {
50
+ onChange?.(event);
51
+ field.onChange(event);
52
+ }, onComplete: (event) => {
53
+ onComplete?.(event);
54
+ }, type, disabled, required }),
55
+ error ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "small", variant: "caption", sentiment: "danger", children: getError({
56
+ label: label || "verification-code-field"
57
+ }, error) }) : null
58
+ ] });
59
+ };
60
+ exports.VerificationCodeField = VerificationCodeField;
@@ -0,0 +1,12 @@
1
+ import { VerificationCode } from '@ultraviolet/ui';
2
+ import type { ComponentProps } from 'react';
3
+ import type { FieldPath, FieldValues } from 'react-hook-form';
4
+ import type { BaseFieldProps } from '../../types';
5
+ type VerificationCodeFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>> = BaseFieldProps<TFieldValues, TName> & Partial<Pick<ComponentProps<typeof VerificationCode>, 'disabled' | 'error' | 'fields' | 'initialValue' | 'onChange' | 'onComplete' | 'placeholder' | 'required' | 'type'>> & {
6
+ className?: string;
7
+ id?: string;
8
+ name: string;
9
+ label?: string;
10
+ };
11
+ export declare const VerificationCodeField: <TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ className, fields, id, label, name, onChange, onComplete, placeholder, required, type, disabled, validate, }: VerificationCodeFieldProps<TFieldValues, TName>) => import("@emotion/react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,60 @@
1
+ import { jsxs, jsx } from "@emotion/react/jsx-runtime";
2
+ import { Stack, Text, VerificationCode } from "@ultraviolet/ui";
3
+ import { useController } from "react-hook-form";
4
+ import { useErrors } from "../../providers/ErrorContext/index.js";
5
+ const VerificationCodeField = ({
6
+ className,
7
+ fields,
8
+ id = "verification-code-input",
9
+ label,
10
+ name,
11
+ onChange,
12
+ onComplete,
13
+ placeholder,
14
+ required,
15
+ type = "number",
16
+ disabled,
17
+ validate
18
+ }) => {
19
+ const {
20
+ getError
21
+ } = useErrors();
22
+ const {
23
+ field,
24
+ fieldState: {
25
+ error
26
+ }
27
+ } = useController({
28
+ name,
29
+ rules: {
30
+ required,
31
+ validate: {
32
+ required: (localValue) => {
33
+ if (required && localValue.length !== (fields ?? 4)) {
34
+ return false;
35
+ }
36
+ return true;
37
+ },
38
+ ...validate
39
+ }
40
+ }
41
+ });
42
+ return /* @__PURE__ */ jsxs(Stack, { className, gap: 1, justifyContent: "center", alignItems: "center", direction: "column", "aria-label": "verification-code-field", children: [
43
+ label ? /* @__PURE__ */ jsx("label", { id: `${id}-label`, htmlFor: `${id}-0`, style: {
44
+ cursor: "pointer",
45
+ flexShrink: 0
46
+ }, children: /* @__PURE__ */ jsx(Text, { as: "p", variant: "body", prominence: "strong", children: label }) }) : null,
47
+ /* @__PURE__ */ jsx(VerificationCode, { inputId: id, error: !!error, placeholder, fields, onChange: (event) => {
48
+ onChange?.(event);
49
+ field.onChange(event);
50
+ }, onComplete: (event) => {
51
+ onComplete?.(event);
52
+ }, type, disabled, required }),
53
+ error ? /* @__PURE__ */ jsx(Text, { as: "small", variant: "caption", sentiment: "danger", children: getError({
54
+ label: label || "verification-code-field"
55
+ }, error) }) : null
56
+ ] });
57
+ };
58
+ export {
59
+ VerificationCodeField
60
+ };
@@ -21,3 +21,4 @@ export { SelectableCardGroupField } from './SelectableCardGroupField';
21
21
  export { SelectInputFieldV2 } from './SelectInputFieldV2';
22
22
  export { UnitInputField } from './UnitInputField';
23
23
  export { SliderField } from './SliderField';
24
+ export { VerificationCodeField } from './VerificationCodeField';
package/dist/index.cjs CHANGED
@@ -26,6 +26,7 @@ const index$k = require("./components/SelectableCardGroupField/index.cjs");
26
26
  const index$l = require("./components/SelectInputFieldV2/index.cjs");
27
27
  const index$m = require("./components/UnitInputField/index.cjs");
28
28
  const index$n = require("./components/SliderField/index.cjs");
29
+ const index$o = require("./components/VerificationCodeField/index.cjs");
29
30
  exports.ErrorProvider = index.ErrorProvider;
30
31
  exports.useErrors = index.useErrors;
31
32
  Object.defineProperty(exports, "useController", {
@@ -76,3 +77,4 @@ exports.SelectableCardGroupField = index$k.SelectableCardGroupField;
76
77
  exports.SelectInputFieldV2 = index$l.SelectInputFieldV2;
77
78
  exports.UnitInputField = index$m.UnitInputField;
78
79
  exports.SliderField = index$n.SliderField;
80
+ exports.VerificationCodeField = index$o.VerificationCodeField;
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ import { SelectableCardGroupField } from "./components/SelectableCardGroupField/
24
24
  import { SelectInputFieldV2 } from "./components/SelectInputFieldV2/index.js";
25
25
  import { UnitInputField } from "./components/UnitInputField/index.js";
26
26
  import { SliderField } from "./components/SliderField/index.js";
27
+ import { VerificationCodeField } from "./components/VerificationCodeField/index.js";
27
28
  export {
28
29
  CheckboxField,
29
30
  CheckboxGroupField,
@@ -49,6 +50,7 @@ export {
49
50
  TimeField,
50
51
  ToggleField,
51
52
  UnitInputField,
53
+ VerificationCodeField,
52
54
  useController,
53
55
  useErrors,
54
56
  useFieldArray,
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from 'react';
1
2
  import type { Control, FieldError, FieldPath, FieldPathValue, FieldValues, Path, PathValue, UseControllerProps, Validate } from 'react-hook-form';
2
3
  export type MetaField = {
3
4
  isInteger?: number | string;
@@ -28,3 +29,21 @@ export type BaseFieldProps<TFieldValues extends FieldValues = FieldValues, TFiel
28
29
  shouldUnregister?: UseControllerProps<TFieldValues, TFieldName>['shouldUnregister'];
29
30
  control?: Control<TFieldValues>;
30
31
  };
32
+ /**
33
+ * Classic prop type where label is a ReactNode and aria-label is a string.
34
+ * One or another is required.
35
+ */
36
+ export type LabelProp = {
37
+ label: ReactNode;
38
+ 'aria-label'?: never;
39
+ } | {
40
+ label?: never;
41
+ 'aria-label': string;
42
+ };
43
+ export type PascalToCamelCase<S extends string> = S extends `${infer P1}${infer P2}` ? `${Lowercase<P1>}${P2}` : S;
44
+ export type RemoveSuffix<S extends string, Suffix extends string> = S extends `${infer Prefix}${Suffix}` ? Prefix : S;
45
+ /**
46
+ * This type removes the suffix from a PascalCase string and converts it to camelCase. Pretty useful for Icon, CategoryIcon and ProductIcon components.
47
+ * Their names being `AddressIcon` but we might need to have `address` as the prop name.
48
+ */
49
+ export type PascalToCamelCaseWithoutSuffix<T extends string, Suffix extends string> = T extends `${infer Prefix}${Suffix}` ? `${PascalToCamelCase<Prefix extends `${infer First}${infer Rest}` ? `${First}${Rest}` : never>}` : never;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/form",
3
- "version": "3.9.7",
3
+ "version": "3.10.0",
4
4
  "description": "Ultraviolet Form",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -69,10 +69,10 @@
69
69
  },
70
70
  "dependencies": {
71
71
  "@babel/runtime": "7.25.7",
72
- "react-hook-form": "7.53.0",
72
+ "react-hook-form": "7.53.1",
73
73
  "react-select": "5.8.1",
74
74
  "@ultraviolet/themes": "1.14.2",
75
- "@ultraviolet/ui": "1.73.1"
75
+ "@ultraviolet/ui": "1.74.0"
76
76
  },
77
77
  "scripts": {
78
78
  "build:profile": "npx vite-bundle-visualizer -c vite.config.ts",