@ultraviolet/form 4.0.2 → 4.0.3

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.
@@ -51,7 +51,9 @@ const DateInputField = ({
51
51
  maxDate: maxDate$1,
52
52
  minDate: minDate$1
53
53
  }, error), format: format || ((value) => {
54
- if (!value) return "";
54
+ if (!value) {
55
+ return "";
56
+ }
55
57
  const date = parseDate(value);
56
58
  return showMonthYearPicker ? date.toLocaleDateString(void 0, {
57
59
  month: "numeric",
@@ -49,7 +49,9 @@ const DateInputField = ({
49
49
  maxDate,
50
50
  minDate
51
51
  }, error), format: format || ((value) => {
52
- if (!value) return "";
52
+ if (!value) {
53
+ return "";
54
+ }
53
55
  const date = parseDate(value);
54
56
  return showMonthYearPicker ? date.toLocaleDateString(void 0, {
55
57
  month: "numeric",
@@ -13,7 +13,9 @@ const KeyValueField = ({
13
13
  addButton,
14
14
  maxSize = 100,
15
15
  readOnly = false,
16
- control
16
+ control,
17
+ onChange,
18
+ onBlur
17
19
  }) => {
18
20
  const {
19
21
  fields,
@@ -23,33 +25,36 @@ const KeyValueField = ({
23
25
  control,
24
26
  name
25
27
  });
28
+ const {
29
+ getValues
30
+ } = reactHookForm.useFormContext();
31
+ const handleFieldChange = () => {
32
+ onChange?.(getValues(name));
33
+ };
34
+ const handleFieldBlur = () => {
35
+ onBlur?.(getValues(name));
36
+ };
26
37
  const canAdd = fields.length !== void 0 && fields.length < maxSize;
27
38
  const maxSizeReachedTooltip = addButton.maxSizeReachedTooltip ?? `Cannot add more than ${maxSize} elements`;
28
39
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { gap: 3, children: [
29
40
  fields.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { gap: 3, children: fields.map((field, index$1) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Row, { alignItems: "end", gap: 2, templateColumns: "1fr 1fr auto", children: [
30
- /* @__PURE__ */ jsxRuntime.jsx(index.TextInputField, { label: inputKey.label, name: `${name}.${index$1}.key`, readOnly, regex: inputKey.regex, required: inputKey.required }),
31
- /* @__PURE__ */ jsxRuntime.jsx(index.TextInputField, { autoComplete: "off", label: inputValue.label, name: `${name}.${index$1}.value`, placeholder: inputValue.placeholder, readOnly, regex: inputValue.regex, required: inputValue.required, type: inputValue.type }),
32
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { "data-testid": `remove-button-${index$1}`, disabled: readOnly, onClick: () => remove(index$1), sentiment: "danger", size: "large", variant: "outlined", children: /* @__PURE__ */ jsxRuntime.jsx(icons.DeleteIcon, {}) })
41
+ /* @__PURE__ */ jsxRuntime.jsx(index.TextInputField, { label: inputKey.label, name: `${name}.${index$1}.key`, onBlur: handleFieldBlur, onChange: handleFieldChange, readOnly, regex: inputKey.regex, required: inputKey.required }),
42
+ /* @__PURE__ */ jsxRuntime.jsx(index.TextInputField, { autoComplete: "off", label: inputValue.label, name: `${name}.${index$1}.value`, onBlur: handleFieldBlur, onChange: handleFieldChange, placeholder: inputValue.placeholder, readOnly, regex: inputValue.regex, required: inputValue.required, type: inputValue.type }),
43
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { "data-testid": `remove-button-${index$1}`, disabled: readOnly, onClick: () => {
44
+ remove(index$1);
45
+ handleFieldChange();
46
+ }, sentiment: "danger", size: "large", variant: "outlined", children: /* @__PURE__ */ jsxRuntime.jsx(icons.DeleteIcon, {}) })
33
47
  ] }, field.id)) }) : null,
34
- /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { direction: "row", justifyContent: "flex-start", children: /* @__PURE__ */ jsxRuntime.jsxs(
35
- ui.Button,
36
- {
37
- "data-testid": "add-button",
38
- disabled: !canAdd || readOnly,
39
- fullWidth: addButton.fullWidth,
40
- onClick: () => append({
41
- key: "",
42
- value: ""
43
- }),
44
- sentiment: "primary",
45
- tooltip: !canAdd ? maxSizeReachedTooltip : addButton.tooltip,
46
- variant: "outlined",
47
- children: [
48
- /* @__PURE__ */ jsxRuntime.jsx(icons.PlusIcon, {}),
49
- addButton.name
50
- ]
51
- }
52
- ) })
48
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { direction: "row", justifyContent: "flex-start", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { "data-testid": "add-button", disabled: !canAdd || readOnly, fullWidth: addButton.fullWidth, onClick: () => {
49
+ append({
50
+ key: "",
51
+ value: ""
52
+ });
53
+ handleFieldChange();
54
+ }, sentiment: "primary", tooltip: !canAdd ? maxSizeReachedTooltip : addButton.tooltip, variant: "outlined", children: [
55
+ /* @__PURE__ */ jsxRuntime.jsx(icons.PlusIcon, {}),
56
+ addButton.name
57
+ ] }) })
53
58
  ] });
54
59
  };
55
60
  exports.KeyValueField = KeyValueField;
@@ -17,6 +17,10 @@ type AddButtonProps = {
17
17
  tooltip?: string;
18
18
  maxSizeReachedTooltip?: string;
19
19
  };
20
+ type KeyValuePair = {
21
+ key: string;
22
+ value: string;
23
+ };
20
24
  type KeyValueFieldProps<TFieldValues extends FieldValues, TFieldArrayName extends FieldArrayPath<TFieldValues>> = {
21
25
  name: TFieldArrayName;
22
26
  inputKey: InputKeyProps;
@@ -25,9 +29,11 @@ type KeyValueFieldProps<TFieldValues extends FieldValues, TFieldArrayName extend
25
29
  maxSize?: number;
26
30
  readOnly?: boolean;
27
31
  control?: Control<TFieldValues>;
32
+ onChange?: (values: KeyValuePair[]) => void;
33
+ onBlur?: (values: KeyValuePair[]) => void;
28
34
  };
29
35
  /**
30
36
  * A React component that allows users to manage key-value pairs
31
37
  */
32
- export declare const KeyValueField: <TFieldValues extends FieldValues = FieldValues, TFieldArrayName extends FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>>({ name, inputKey, inputValue, addButton, maxSize, readOnly, control, }: KeyValueFieldProps<TFieldValues, TFieldArrayName>) => import("@emotion/react/jsx-runtime").JSX.Element;
38
+ export declare const KeyValueField: <TFieldValues extends FieldValues = FieldValues, TFieldArrayName extends FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>>({ name, inputKey, inputValue, addButton, maxSize, readOnly, control, onChange, onBlur, }: KeyValueFieldProps<TFieldValues, TFieldArrayName>) => import("@emotion/react/jsx-runtime").JSX.Element;
33
39
  export {};
@@ -2,7 +2,7 @@
2
2
  import { jsxs, jsx } from "@emotion/react/jsx-runtime";
3
3
  import { DeleteIcon, PlusIcon } from "@ultraviolet/icons";
4
4
  import { Stack, Row, Button } from "@ultraviolet/ui";
5
- import { useFieldArray } from "react-hook-form";
5
+ import { useFieldArray, useFormContext } from "react-hook-form";
6
6
  import { TextInputField } from "../TextInputField/index.js";
7
7
  const KeyValueField = ({
8
8
  name,
@@ -11,7 +11,9 @@ const KeyValueField = ({
11
11
  addButton,
12
12
  maxSize = 100,
13
13
  readOnly = false,
14
- control
14
+ control,
15
+ onChange,
16
+ onBlur
15
17
  }) => {
16
18
  const {
17
19
  fields,
@@ -21,33 +23,36 @@ const KeyValueField = ({
21
23
  control,
22
24
  name
23
25
  });
26
+ const {
27
+ getValues
28
+ } = useFormContext();
29
+ const handleFieldChange = () => {
30
+ onChange?.(getValues(name));
31
+ };
32
+ const handleFieldBlur = () => {
33
+ onBlur?.(getValues(name));
34
+ };
24
35
  const canAdd = fields.length !== void 0 && fields.length < maxSize;
25
36
  const maxSizeReachedTooltip = addButton.maxSizeReachedTooltip ?? `Cannot add more than ${maxSize} elements`;
26
37
  return /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
27
38
  fields.length > 0 ? /* @__PURE__ */ jsx(Stack, { gap: 3, children: fields.map((field, index) => /* @__PURE__ */ jsxs(Row, { alignItems: "end", gap: 2, templateColumns: "1fr 1fr auto", children: [
28
- /* @__PURE__ */ jsx(TextInputField, { label: inputKey.label, name: `${name}.${index}.key`, readOnly, regex: inputKey.regex, required: inputKey.required }),
29
- /* @__PURE__ */ jsx(TextInputField, { autoComplete: "off", label: inputValue.label, name: `${name}.${index}.value`, placeholder: inputValue.placeholder, readOnly, regex: inputValue.regex, required: inputValue.required, type: inputValue.type }),
30
- /* @__PURE__ */ jsx(Button, { "data-testid": `remove-button-${index}`, disabled: readOnly, onClick: () => remove(index), sentiment: "danger", size: "large", variant: "outlined", children: /* @__PURE__ */ jsx(DeleteIcon, {}) })
39
+ /* @__PURE__ */ jsx(TextInputField, { label: inputKey.label, name: `${name}.${index}.key`, onBlur: handleFieldBlur, onChange: handleFieldChange, readOnly, regex: inputKey.regex, required: inputKey.required }),
40
+ /* @__PURE__ */ jsx(TextInputField, { autoComplete: "off", label: inputValue.label, name: `${name}.${index}.value`, onBlur: handleFieldBlur, onChange: handleFieldChange, placeholder: inputValue.placeholder, readOnly, regex: inputValue.regex, required: inputValue.required, type: inputValue.type }),
41
+ /* @__PURE__ */ jsx(Button, { "data-testid": `remove-button-${index}`, disabled: readOnly, onClick: () => {
42
+ remove(index);
43
+ handleFieldChange();
44
+ }, sentiment: "danger", size: "large", variant: "outlined", children: /* @__PURE__ */ jsx(DeleteIcon, {}) })
31
45
  ] }, field.id)) }) : null,
32
- /* @__PURE__ */ jsx(Stack, { direction: "row", justifyContent: "flex-start", children: /* @__PURE__ */ jsxs(
33
- Button,
34
- {
35
- "data-testid": "add-button",
36
- disabled: !canAdd || readOnly,
37
- fullWidth: addButton.fullWidth,
38
- onClick: () => append({
39
- key: "",
40
- value: ""
41
- }),
42
- sentiment: "primary",
43
- tooltip: !canAdd ? maxSizeReachedTooltip : addButton.tooltip,
44
- variant: "outlined",
45
- children: [
46
- /* @__PURE__ */ jsx(PlusIcon, {}),
47
- addButton.name
48
- ]
49
- }
50
- ) })
46
+ /* @__PURE__ */ jsx(Stack, { direction: "row", justifyContent: "flex-start", children: /* @__PURE__ */ jsxs(Button, { "data-testid": "add-button", disabled: !canAdd || readOnly, fullWidth: addButton.fullWidth, onClick: () => {
47
+ append({
48
+ key: "",
49
+ value: ""
50
+ });
51
+ handleFieldChange();
52
+ }, sentiment: "primary", tooltip: !canAdd ? maxSizeReachedTooltip : addButton.tooltip, variant: "outlined", children: [
53
+ /* @__PURE__ */ jsx(PlusIcon, {}),
54
+ addButton.name
55
+ ] }) })
51
56
  ] });
52
57
  };
53
58
  export {
@@ -1,5 +1,5 @@
1
- declare const _default: {
1
+ declare const validators: {
2
2
  maxDate: (maxDate?: Date) => (value: Date | [Date, Date]) => boolean;
3
3
  minDate: (maxDate?: Date) => (value: Date | [Date, Date]) => boolean;
4
4
  };
5
- export default _default;
5
+ export default validators;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const isInteger = (step) => (value) => {
4
- if (value === void 0 || step === void 0) return true;
4
+ if (value === void 0 || step === void 0) {
5
+ return true;
6
+ }
5
7
  if (Number.isInteger(step)) {
6
8
  return Number.isInteger(value) && Number.isInteger(value);
7
9
  }
@@ -1,5 +1,7 @@
1
1
  const isInteger = (step) => (value) => {
2
- if (value === void 0 || step === void 0) return true;
2
+ if (value === void 0 || step === void 0) {
3
+ return true;
4
+ }
3
5
  if (Number.isInteger(step)) {
4
6
  return Number.isInteger(value) && Number.isInteger(value);
5
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/form",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "description": "Ultraviolet Form",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -55,25 +55,25 @@
55
55
  "@emotion/styled": "11.14.1",
56
56
  "react": "18.x || 19.x",
57
57
  "react-dom": "18.x || 19.x",
58
- "@ultraviolet/ui": "2.0.2"
58
+ "@ultraviolet/ui": "2.0.3"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@babel/core": "7.28.0",
62
62
  "@emotion/react": "11.14.0",
63
63
  "@emotion/styled": "11.14.1",
64
64
  "@types/final-form-focus": "1.1.7",
65
- "@types/react": "19.1.8",
66
- "@types/react-dom": "19.1.6",
67
- "react": "19.1.0",
68
- "react-dom": "19.1.0",
69
- "@ultraviolet/ui": "2.0.2",
65
+ "@types/react": "19.1.9",
66
+ "@types/react-dom": "19.1.7",
67
+ "react": "19.1.1",
68
+ "react-dom": "19.1.1",
69
+ "@ultraviolet/ui": "2.0.3",
70
70
  "@utils/test": "0.0.1"
71
71
  },
72
72
  "dependencies": {
73
- "@babel/runtime": "7.27.6",
73
+ "@babel/runtime": "7.28.2",
74
74
  "react-hook-form": "7.55.0",
75
75
  "react-select": "5.10.0",
76
- "@ultraviolet/icons": "4.0.1",
76
+ "@ultraviolet/icons": "4.0.2",
77
77
  "@ultraviolet/themes": "2.0.0"
78
78
  },
79
79
  "scripts": {