@ultraviolet/form 2.2.0 → 2.3.1

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.
@@ -0,0 +1,83 @@
1
+ import { Stack, Row, Button } from '@ultraviolet/ui';
2
+ import { useFieldArray } from 'react-hook-form';
3
+ import { TextInputField } from '../TextInputField/index.js';
4
+ import { jsxs, jsx } from '@emotion/react/jsx-runtime';
5
+
6
+ /**
7
+ * A React component that allows users to manage key-value pairs
8
+ */
9
+ const KeyValueField = ({
10
+ name,
11
+ inputKey,
12
+ inputValue,
13
+ addButton,
14
+ maxSize = 100,
15
+ readonly = false,
16
+ control
17
+ }) => {
18
+ const {
19
+ fields,
20
+ append,
21
+ remove
22
+ } = useFieldArray({
23
+ name,
24
+ control
25
+ });
26
+ const canAdd = fields.length !== undefined && fields.length < maxSize;
27
+ const maxSizeReachedTooltip = addButton.maxSizeReachedTooltip ?? `Cannot add more than ${maxSize} elements`;
28
+ return jsxs(Stack, {
29
+ gap: 3,
30
+ children: [fields.length ? jsx(Stack, {
31
+ gap: 2,
32
+ children: fields.map((field, index) => jsxs(Row, {
33
+ templateColumns: "1fr 1fr auto",
34
+ gap: 2,
35
+ children: [jsx(TextInputField, {
36
+ readOnly: readonly,
37
+ required: inputKey.required,
38
+ name: `${name}.${index}.key`,
39
+ label: inputKey.label,
40
+ regex: inputKey.regex
41
+ }), jsx(TextInputField, {
42
+ readOnly: readonly,
43
+ required: inputValue.required,
44
+ name: `${name}.${index}.value`,
45
+ label: inputValue.label,
46
+ placeholder: inputValue.placeholder,
47
+ type: inputValue.type,
48
+ autoComplete: "off",
49
+ regex: inputValue.regex
50
+ }), jsx(Button, {
51
+ disabled: readonly,
52
+ "data-testid": `remove-button-${index}`,
53
+ icon: "delete",
54
+ variant: "outlined",
55
+ sentiment: "danger",
56
+ size: "large",
57
+ onClick: () => remove(index)
58
+ })]
59
+ }, field.id))
60
+ }) : null, jsx(Stack, {
61
+ direction: "row",
62
+ justifyContent: "flex-start",
63
+ children: jsx(Button, {
64
+ "data-testid": "add-button",
65
+ icon: "plus",
66
+ variant: "filled",
67
+ sentiment: "neutral",
68
+ fullWidth: addButton.fullWidth,
69
+ disabled: !canAdd || readonly,
70
+ tooltip: !canAdd ? maxSizeReachedTooltip : addButton.tooltip
71
+ // @ts-expect-error can't infer properly
72
+ ,
73
+ onClick: () => append({
74
+ key: '',
75
+ value: ''
76
+ }),
77
+ children: addButton.name
78
+ })
79
+ })]
80
+ });
81
+ };
82
+
83
+ export { KeyValueField };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { Checkbox, CheckboxGroup, DateInput, Radio, SelectInput, SelectableCard,
3
3
  import * as react from 'react';
4
4
  import { ComponentProps, ReactNode, FocusEvent, ForwardedRef, FocusEventHandler, Ref, JSX } from 'react';
5
5
  import * as react_hook_form from 'react-hook-form';
6
- import { FieldValues, FieldPath, Validate, PathValue, Path, UseControllerProps, FieldError, UseFormReturn, DefaultValues, FieldErrors, FieldPathValue, DeepPartial, ArrayPath, FieldArray } from 'react-hook-form';
6
+ import { FieldValues, FieldPath, Validate, PathValue, Path, UseControllerProps, FieldError, UseFormReturn, DefaultValues, FieldErrors, FieldArrayPath, Control, FieldPathValue, DeepPartial, ArrayPath, FieldArray } from 'react-hook-form';
7
7
  export { ArrayPath, Control, ControllerRenderProps, DeepPartial, FieldArray, FieldArrayPath, FieldArrayPathValue, FieldErrors, FieldPath, FieldPathByValue, FieldPathValue, FieldPathValues, FieldValues, Path, PathValue, UseFieldArrayMove, UseFieldArrayRemove, UseFormReturn, UseFormSetValue, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch } from 'react-hook-form';
8
8
  import { CSSObject, Theme, css } from '@emotion/react';
9
9
  import Select, { OptionProps, GroupBase, Props, CommonProps } from 'react-select';
@@ -323,6 +323,35 @@ declare const RadioGroupField: {
323
323
  }) => _emotion_react_jsx_runtime.JSX.Element;
324
324
  };
325
325
 
326
+ type InputKeyProps = {
327
+ label: ComponentProps<typeof TextInputField>['label'];
328
+ required?: ComponentProps<typeof TextInputField>['required'];
329
+ regex?: ComponentProps<typeof TextInputField>['regex'];
330
+ };
331
+ type InputValueProps = {
332
+ type?: ComponentProps<typeof TextInputField>['type'];
333
+ placeholder?: ComponentProps<typeof TextInputField>['placeholder'];
334
+ } & InputKeyProps;
335
+ type AddButtonProps = {
336
+ name: ComponentProps<typeof Button>['children'];
337
+ fullWidth?: ComponentProps<typeof Button>['fullWidth'];
338
+ tooltip?: string;
339
+ maxSizeReachedTooltip?: string;
340
+ };
341
+ type KeyValueFieldProps<TFieldValues extends FieldValues, TFieldArrayName extends FieldArrayPath<TFieldValues>> = {
342
+ name: TFieldArrayName;
343
+ inputKey: InputKeyProps;
344
+ inputValue: InputValueProps;
345
+ addButton: AddButtonProps;
346
+ maxSize?: number;
347
+ readonly?: boolean;
348
+ control?: Control<TFieldValues>;
349
+ };
350
+ /**
351
+ * A React component that allows users to manage key-value pairs
352
+ */
353
+ declare const KeyValueField: <TFieldValues extends FieldValues = FieldValues, TFieldArrayName extends FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>>({ name, inputKey, inputValue, addButton, maxSize, readonly, control, }: KeyValueFieldProps<TFieldValues, TFieldArrayName>) => _emotion_react_jsx_runtime.JSX.Element;
354
+
326
355
  type ErrorContextValue = {
327
356
  errors: RequiredErrors;
328
357
  getError: (meta: MetaField, error?: FieldError) => string | undefined;
@@ -449,4 +478,4 @@ declare const useFieldArrayDeprecated: <T, TFieldValues extends FieldValues = Fi
449
478
  };
450
479
  };
451
480
 
452
- export { type BaseFieldProps, CheckboxField, CheckboxGroupField, DateField, ErrorProvider, FORM_ERROR, Form, type FormErrors, type FormProps, NumberInputField, RadioField, RadioGroupField, SelectInputField, SelectableCardField, Submit, SubmitErrorAlert, TagInputField, TextInputField, TimeField, ToggleField, useErrors, useFieldArrayDeprecated, useFieldDeprecated, useFormDeprecated, useFormStateDeprecated, useOnFieldChange };
481
+ export { type BaseFieldProps, CheckboxField, CheckboxGroupField, DateField, ErrorProvider, FORM_ERROR, Form, type FormErrors, type FormProps, KeyValueField, NumberInputField, RadioField, RadioGroupField, SelectInputField, SelectableCardField, Submit, SubmitErrorAlert, TagInputField, TextInputField, TimeField, ToggleField, useErrors, useFieldArrayDeprecated, useFieldDeprecated, useFormDeprecated, useFormStateDeprecated, useOnFieldChange };
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export { CheckboxField } from './components/CheckboxField/index.js';
5
5
  export { CheckboxGroupField } from './components/CheckboxGroupField/index.js';
6
6
  export { DateField } from './components/DateField/index.js';
7
7
  export { Form } from './components/Form/index.js';
8
+ export { KeyValueField } from './components/KeyValueField/index.js';
8
9
  export { RadioField } from './components/RadioField/index.js';
9
10
  export { SelectableCardField } from './components/SelectableCardField/index.js';
10
11
  export { SelectInputField } from './components/SelectInputField/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/form",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "Ultraviolet Form",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "@emotion/styled": "11.11.0",
54
54
  "react-select": "5.8.0",
55
55
  "react-hook-form": "7.49.3",
56
- "@ultraviolet/ui": "1.31.0"
56
+ "@ultraviolet/ui": "1.31.1"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "rollup -c ../../rollup.config.mjs",