@weareconceptstudio/form 0.0.3 → 0.0.5

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 (77) hide show
  1. package/dist/FormConfig.d.ts +5 -0
  2. package/dist/FormConfig.js +19 -0
  3. package/dist/checkbox/BaseCheckbox.d.ts +3 -0
  4. package/dist/checkbox/BaseCheckbox.js +51 -0
  5. package/dist/checkbox/index.js +15 -4
  6. package/dist/color-picker/index.d.ts +4 -1
  7. package/dist/color-picker/index.js +4 -4
  8. package/dist/date-picker/index.d.ts +6 -1
  9. package/dist/date-picker/index.js +4 -4
  10. package/dist/error-message/index.js +2 -2
  11. package/dist/form/BaseForm.d.ts +22 -20
  12. package/dist/form/BaseForm.js +38 -55
  13. package/dist/form/Builder/index.d.ts +9 -0
  14. package/dist/form/Builder/index.js +46 -0
  15. package/dist/form/Builder/style.d.ts +2 -0
  16. package/dist/form/Builder/style.js +3 -0
  17. package/dist/form/Item/index.d.ts +12 -10
  18. package/dist/form/Item/index.js +25 -18
  19. package/dist/form/hooks/rules.d.ts +3 -0
  20. package/dist/form/hooks/rules.js +44 -0
  21. package/dist/form/hooks/useEvent.d.ts +1 -0
  22. package/dist/form/hooks/useEvent.js +12 -0
  23. package/dist/form/hooks/useFormInstance.js +3 -0
  24. package/dist/form/hooks/useInput.d.ts +12 -0
  25. package/dist/form/hooks/useInput.js +46 -0
  26. package/dist/form/index.d.ts +6 -17
  27. package/dist/form/index.js +3 -2
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.js +4 -0
  30. package/dist/input/BaseInput/index.d.ts +4 -2
  31. package/dist/input/BaseInput/index.js +13 -31
  32. package/dist/input/Input.d.ts +4 -1
  33. package/dist/input/Input.js +15 -16
  34. package/dist/input/Number/index.d.ts +4 -1
  35. package/dist/input/Number/index.js +27 -4
  36. package/dist/input/Password/icons.d.ts +1 -1
  37. package/dist/input/Password/icons.js +6 -6
  38. package/dist/input/Password/index.d.ts +4 -1
  39. package/dist/input/Password/index.js +5 -5
  40. package/dist/input/TextArea/index.d.ts +4 -1
  41. package/dist/input/TextArea/index.js +8 -9
  42. package/dist/input/index.d.ts +10 -1
  43. package/dist/input/index.js +6 -4
  44. package/dist/phone-number/index.d.ts +7 -0
  45. package/dist/phone-number/index.js +13 -0
  46. package/dist/radio/BaseRadio.js +18 -5
  47. package/dist/radio/Group.js +19 -2
  48. package/dist/radio/index.js +2 -2
  49. package/dist/select/icons.d.ts +3 -0
  50. package/dist/select/icons.js +6 -0
  51. package/dist/select/index.d.ts +4 -1
  52. package/dist/select/index.js +57 -20
  53. package/dist/styles/formStyle.d.ts +2 -0
  54. package/dist/styles/formStyle.js +585 -0
  55. package/dist/styles/theme.d.ts +2 -0
  56. package/dist/styles/theme.js +113 -0
  57. package/dist/styles/variables.d.ts +2 -0
  58. package/dist/styles/variables.js +246 -0
  59. package/dist/translations/en.d.ts +52 -0
  60. package/dist/translations/en.js +52 -0
  61. package/dist/translations/index.d.ts +54 -0
  62. package/dist/translations/index.js +2 -0
  63. package/dist/upload/UploadButton/index.d.ts +3 -0
  64. package/dist/upload/UploadButton/index.js +41 -0
  65. package/dist/upload/UploadButton/style.d.ts +2 -0
  66. package/dist/upload/UploadButton/style.js +24 -0
  67. package/dist/upload/UploadList/ListItem/index.d.ts +5 -0
  68. package/dist/upload/UploadList/ListItem/index.js +11 -0
  69. package/dist/upload/UploadList/index.d.ts +3 -0
  70. package/dist/upload/UploadList/index.js +11 -0
  71. package/dist/upload/UploadList/style.d.ts +2 -0
  72. package/dist/upload/UploadList/style.js +13 -0
  73. package/dist/upload/index.d.ts +4 -1
  74. package/dist/upload/index.js +15 -5
  75. package/dist/upload/utils.d.ts +9 -0
  76. package/dist/upload/utils.js +64 -0
  77. package/package.json +31 -34
@@ -0,0 +1,5 @@
1
+ export function FormConfig({ fontFamily, children }: {
2
+ fontFamily?: string;
3
+ children: any;
4
+ }): React.JSX.Element;
5
+ import React from 'react';
@@ -0,0 +1,19 @@
1
+ import React, { useEffect } from 'react';
2
+ import { useTranslation } from '@weareconceptstudio/core';
3
+ import { ThemeProvider } from 'styled-components';
4
+ //* Translations
5
+ import translations from './translations';
6
+ //* Styles
7
+ import theme from './styles/theme';
8
+ import FormVariables from './styles/variables';
9
+ import FormStyle from './styles/formStyle';
10
+ export const FormConfig = ({ fontFamily = 'core_Font', children }) => {
11
+ const { addTranslation } = useTranslation();
12
+ useEffect(() => {
13
+ addTranslation(translations, 'prepend');
14
+ }, []);
15
+ return (React.createElement(ThemeProvider, { theme: theme },
16
+ React.createElement(FormVariables, { fontFamily: fontFamily }),
17
+ React.createElement(FormStyle, null),
18
+ children));
19
+ };
@@ -0,0 +1,3 @@
1
+ export default BaseCheckbox;
2
+ declare const BaseCheckbox: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
3
+ import React from 'react';
@@ -0,0 +1,51 @@
1
+ import React, { forwardRef, useRef, useImperativeHandle } from 'react';
2
+ import { useMergedState } from '@weareconceptstudio/core';
3
+ import classNames from 'classnames';
4
+ const BaseCheckbox = forwardRef((props, ref) => {
5
+ const { prefixCls = 'checkbox', className, style, checked, disabled, defaultChecked = false, type = 'checkbox', title, onChange, ...inputProps } = props;
6
+ const inputRef = useRef(null);
7
+ const holderRef = useRef(null);
8
+ const [rawValue, setRawValue] = useMergedState(defaultChecked, {
9
+ value: checked,
10
+ });
11
+ useImperativeHandle(ref, () => ({
12
+ focus: (options) => {
13
+ inputRef.current?.focus(options);
14
+ },
15
+ blur: () => {
16
+ inputRef.current?.blur();
17
+ },
18
+ input: inputRef.current,
19
+ nativeElement: holderRef.current,
20
+ }));
21
+ const classString = classNames(prefixCls, className, {
22
+ [`${prefixCls}-checked`]: rawValue,
23
+ [`${prefixCls}-disabled`]: disabled,
24
+ });
25
+ const handleChange = (e) => {
26
+ if (disabled) {
27
+ return;
28
+ }
29
+ if (!('checked' in props)) {
30
+ setRawValue(e.target.checked);
31
+ }
32
+ onChange?.({
33
+ target: {
34
+ ...props,
35
+ type,
36
+ checked: e.target.checked,
37
+ },
38
+ stopPropagation() {
39
+ e.stopPropagation();
40
+ },
41
+ preventDefault() {
42
+ e.preventDefault();
43
+ },
44
+ nativeEvent: e.nativeEvent,
45
+ });
46
+ };
47
+ return (React.createElement("span", { className: classString, title: title, style: style, ref: holderRef },
48
+ React.createElement("input", { type: type, className: `${prefixCls}-input`, ref: inputRef, onChange: handleChange, disabled: disabled, checked: !!rawValue, ...inputProps }),
49
+ React.createElement("span", { className: `${prefixCls}-inner` })));
50
+ });
51
+ export default BaseCheckbox;
@@ -1,8 +1,19 @@
1
1
  import React, { forwardRef } from 'react';
2
- const Checkbox = forwardRef(({ type = 'checkbox', children, ...restProps }, forwardRef) => {
3
- return (React.createElement("label", null,
4
- React.createElement("input", { type: type, ...forwardRef, ...restProps }),
5
- children !== undefined && React.createElement("span", null, children)));
2
+ import BaseCheckbox from './BaseCheckbox';
3
+ import classNames from 'classnames';
4
+ const Checkbox = forwardRef((props, forwardRef) => {
5
+ const { type = 'checkbox', prefixCls = 'checkbox', children, ...restProps } = props;
6
+ const checkboxProps = {
7
+ ref: forwardRef,
8
+ ...restProps,
9
+ };
10
+ const classString = classNames(`${prefixCls}-wrapper`, {
11
+ [`${prefixCls}-wrapper-checked`]: checkboxProps.checked,
12
+ [`${prefixCls}-wrapper-disabled`]: checkboxProps.disabled,
13
+ });
14
+ return (React.createElement("label", { className: classString },
15
+ React.createElement(BaseCheckbox, { ...checkboxProps }),
16
+ children !== undefined && React.createElement("span", { className: `${prefixCls}-content` }, children)));
6
17
  });
7
18
  if (process.env.NODE_ENV !== 'production') {
8
19
  Checkbox.displayName = 'Checkbox';
@@ -1,3 +1,6 @@
1
1
  export default ColorPicker;
2
- declare const ColorPicker: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
2
+ declare function ColorPicker(props: any): React.JSX.Element;
3
+ declare namespace ColorPicker {
4
+ let displayName: string;
5
+ }
3
6
  import React from 'react';
@@ -1,7 +1,7 @@
1
- import React, { forwardRef } from 'react';
2
- const ColorPicker = forwardRef((props, forwardRef) => {
3
- return (React.createElement("input", { type: 'color', ...forwardRef }));
4
- });
1
+ import React from 'react';
2
+ const ColorPicker = (props) => {
3
+ return React.createElement("input", { type: 'color' });
4
+ };
5
5
  if (process.env.NODE_ENV !== 'production') {
6
6
  ColorPicker.displayName = 'ColorPicker';
7
7
  }
@@ -1,3 +1,8 @@
1
1
  export default DatePicker;
2
- declare const DatePicker: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
2
+ declare function DatePicker({ type }: {
3
+ type?: string;
4
+ }): React.JSX.Element;
5
+ declare namespace DatePicker {
6
+ let displayName: string;
7
+ }
3
8
  import React from 'react';
@@ -1,11 +1,11 @@
1
- import React, { forwardRef } from 'react';
1
+ import React from 'react';
2
2
  /*
3
3
  types - default=date,datetime-local,month,time,week
4
4
  *
5
5
  */
6
- const DatePicker = forwardRef(({ type = 'date' }, forwardRef) => {
7
- return (React.createElement("input", { type: type, ...forwardRef }));
8
- });
6
+ const DatePicker = ({ type = 'date' }) => {
7
+ return React.createElement("input", { type: type });
8
+ };
9
9
  if (process.env.NODE_ENV !== 'production') {
10
10
  DatePicker.displayName = 'DatePicker';
11
11
  }
@@ -13,10 +13,10 @@ const ErrorMessage = ({ as, errors, name, message, render, ...rest }) => {
13
13
  return isValidElement(as)
14
14
  ? cloneElement(as, props)
15
15
  : render
16
- ? (render({
16
+ ? render({
17
17
  message: messageFromRegister || message,
18
18
  messages: types,
19
- }))
19
+ })
20
20
  : createElement(as || Fragment, props);
21
21
  };
22
22
  if (process.env.NODE_ENV !== 'production') {
@@ -1,21 +1,23 @@
1
- export default BaseForm;
2
- declare function BaseForm({ initialValues: defaultValues, values, children, onSubmit, layout, mode, reValidateMode, errors, resetOptions, criteriaMode, shouldFocusError, delayError, shouldUseNativeValidation, shouldUnregister, }: {
3
- initialValues: any;
4
- values: any;
5
- children: any;
6
- onSubmit: any;
7
- layout?: string;
8
- mode?: string;
9
- reValidateMode: any;
10
- errors: any;
11
- resetOptions: any;
12
- criteriaMode: any;
13
- shouldFocusError: any;
14
- delayError: any;
15
- shouldUseNativeValidation: any;
16
- shouldUnregister: any;
17
- }): React.JSX.Element;
18
- declare namespace BaseForm {
19
- let displayName: string;
1
+ import React, { ReactNode } from 'react';
2
+ import { FieldValues } from 'react-hook-form';
3
+ interface BaseFormProps<T extends FieldValues> {
4
+ initialValues?: T;
5
+ values?: T;
6
+ children: ReactNode;
7
+ onSubmit: (values: T) => Promise<any>;
8
+ mode?: 'onChange' | 'onBlur' | 'onSubmit' | 'all';
9
+ reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit';
10
+ errors?: any;
11
+ resetOptions?: Record<string, any>;
12
+ criteriaMode?: 'firstError' | 'all';
13
+ shouldFocusError?: boolean;
14
+ delayError?: number;
15
+ shouldUseNativeValidation?: boolean;
16
+ shouldUnregister?: boolean;
17
+ className?: string;
20
18
  }
21
- import React from 'react';
19
+ declare const BaseForm: {
20
+ <T extends FieldValues>({ initialValues: defaultValues, values, children, onSubmit: onFinish, mode, reValidateMode, errors, resetOptions, criteriaMode, shouldFocusError, delayError, shouldUseNativeValidation, shouldUnregister, className, }: BaseFormProps<T>): React.JSX.Element;
21
+ displayName: string;
22
+ };
23
+ export default BaseForm;
@@ -1,67 +1,50 @@
1
- import React from 'react';
2
- import { FormProvider, useForm } from "react-hook-form";
3
- import styled from 'styled-components';
4
- // initialValues: object || async () => fetch('/api-endpoint')
5
- // values: object
6
- // children: React elements
7
- // onSubmit: func (values) => {}
8
- // layout: vertical | horizontal
9
- // mode: onChange | onBlur | onSubmit | onTouched | all = 'onSubmit'
10
- // reValidateMode: onChange | onBlur | onSubmit = 'onChange'
11
- // errors: Reactive errors to update the form errors.
12
- // resetOptions: Option to reset form state update while updating new form values.
13
- // criteriaMode: Display all validation errors or one at a time. (firstError | all)
14
- // shouldFocusError: Enable or disable built-in focus management.
15
- // delayError: Delay error from appearing instantly.
16
- // shouldUseNativeValidation: Use browser built-in form constraint API.
17
- // shouldUnregister: Enable and disable input unregister after unmount.
18
- /**
19
- * defaultValues are cached. To reset them, use the reset API.
20
- * defaultValues will be included in the submission result by default.
21
- * values will get updated when values props updates
22
- * resetOptions: {
23
- keepDirtyValues: true, // user-interacted input will be retained
24
- keepErrors: true, // input errors will be retained with value update
25
- },
26
- * criteriaMode:{
27
- When set to firstError (default), only the first error from each field will be gathered.
28
- When set to all, all errors from each field will be gathered.
29
- }
30
- * shouldFocusError: When set to true (default), and the user submits a form that fails validation, focus is set on the first field with an error.
31
- * delayError: number
32
- *
33
- */
34
- const StyledForm = styled.form `
35
- &.vertical {
36
- .form-item-row {
37
- flex-direction: column;
38
- }
39
- }
40
-
41
- .form-item-row {
42
- display: flex;
43
- }
44
-
45
- .form-item {
46
- margin-bottom: 24px;
47
- }
48
- `;
49
- const BaseForm = ({ initialValues: defaultValues, values, children, onSubmit, layout = 'vertical', mode = 'onChange', reValidateMode, errors, resetOptions, criteriaMode, shouldFocusError, delayError, shouldUseNativeValidation, shouldUnregister, }) => {
1
+ import React, { useCallback } from 'react';
2
+ import { FormProvider, useForm } from 'react-hook-form';
3
+ import { Text } from '@weareconceptstudio/core';
4
+ import classNames from 'classnames';
5
+ const BaseForm = ({ initialValues: defaultValues, values, children, onSubmit: onFinish, mode = 'onChange', reValidateMode = 'onChange', errors, resetOptions, criteriaMode, shouldFocusError, delayError = 0, shouldUseNativeValidation, shouldUnregister, className, }) => {
50
6
  const methods = useForm({
51
- defaultValues,
52
- values,
53
7
  mode,
54
- reValidateMode,
55
8
  errors,
9
+ values,
10
+ delayError,
56
11
  resetOptions,
57
12
  criteriaMode,
13
+ // @ts-ignore
14
+ defaultValues,
15
+ reValidateMode,
58
16
  shouldFocusError,
59
- delayError,
60
- shouldUseNativeValidation,
61
17
  shouldUnregister,
18
+ shouldUseNativeValidation,
62
19
  });
20
+ const onSubmit = useCallback((values) => {
21
+ return onFinish(values).catch(({ data, status, ...err }) => {
22
+ if (status === 422) {
23
+ for (const key in data.errors) {
24
+ if (data.errors.hasOwnProperty(key)) {
25
+ // @ts-ignore
26
+ methods.setError(key, {
27
+ type: 'manual',
28
+ message: data.errors[key][0],
29
+ });
30
+ }
31
+ }
32
+ }
33
+ else {
34
+ methods.setError('root.serverError', {
35
+ type: String(status),
36
+ message: data?.message || 'serverError',
37
+ });
38
+ }
39
+ });
40
+ }, [methods, onFinish]);
63
41
  return (React.createElement(FormProvider, { ...methods },
64
- React.createElement(StyledForm, { onSubmit: methods.handleSubmit(onSubmit), className: layout }, children)));
42
+ methods.formState.errors.root?.serverError && (React.createElement("div", { className: "global-error-wrap" },
43
+ React.createElement(Text, { className: 'backend-error', text: methods.formState.errors.root?.serverError.message }),
44
+ React.createElement(Text, { className: 'frontend-error', text: 'globalError' }))),
45
+ React.createElement("form", { onSubmit: methods.handleSubmit(onSubmit), className: classNames({
46
+ [className]: !!className,
47
+ }) }, children)));
65
48
  };
66
49
  if (process.env.NODE_ENV !== 'production') {
67
50
  BaseForm.displayName = 'BaseForm';
@@ -0,0 +1,9 @@
1
+ export default FormBuilder;
2
+ declare function FormBuilder({ className, onSubmit, formOptions, fields, children }: {
3
+ className?: string;
4
+ onSubmit: any;
5
+ formOptions?: {};
6
+ fields?: any[];
7
+ children: any;
8
+ }): React.JSX.Element;
9
+ import React from 'react';
@@ -0,0 +1,46 @@
1
+ import React, { useMemo, cloneElement, isValidElement } from 'react';
2
+ import classNames from 'classnames';
3
+ //* Components
4
+ import Form from '../';
5
+ import Input from '../../input';
6
+ import Checkbox from '../../checkbox';
7
+ import Radio from '../../radio';
8
+ import PhoneNumber from '../../phone-number';
9
+ import Select from '../../select';
10
+ import Upload from '../../upload';
11
+ import DatePicker from '../../date-picker';
12
+ import ColorPicker from '../../color-picker';
13
+ //* Style
14
+ import BuilderStyle from './style';
15
+ const formElements = {
16
+ 'input': React.createElement(Input, null),
17
+ 'password': React.createElement(Input.Password, null),
18
+ 'textarea': React.createElement(Input.TextArea, null),
19
+ 'number': React.createElement(Input.Number, null),
20
+ 'checkbox': React.createElement(Checkbox, null),
21
+ 'radio': React.createElement(Radio, null),
22
+ 'phone': React.createElement(PhoneNumber, null),
23
+ 'select': React.createElement(Select, null),
24
+ 'upload': React.createElement(Upload, null),
25
+ 'date': React.createElement(DatePicker, null),
26
+ 'color': React.createElement(ColorPicker, null),
27
+ };
28
+ const FormBuilder = ({ className = '', onSubmit, formOptions = {}, fields = [], children }) => {
29
+ const elements = useMemo(() => {
30
+ return fields.map((field, index) => {
31
+ if (field.fieldType == 'empty') {
32
+ return (React.createElement("div", { className: 'empty-form-item', ...field.fieldProps }));
33
+ }
34
+ else {
35
+ return isValidElement(formElements[field.fieldType]) ? (React.createElement(Form.Item, { key: index, ...field.labelProps }, cloneElement(formElements[field.fieldType], field.fieldProps))) : null;
36
+ }
37
+ });
38
+ }, [fields]);
39
+ const classString = classNames('form-builder', {
40
+ [className]: className,
41
+ });
42
+ return (React.createElement(Form, { ...formOptions, onSubmit: onSubmit },
43
+ React.createElement(BuilderStyle, { className: classString }, elements),
44
+ children));
45
+ };
46
+ export default FormBuilder;
@@ -0,0 +1,2 @@
1
+ export default BuilderStyle;
2
+ declare const BuilderStyle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
@@ -0,0 +1,3 @@
1
+ import styled from 'styled-components';
2
+ const BuilderStyle = styled.div ``;
3
+ export default BuilderStyle;
@@ -1,11 +1,13 @@
1
- export default FormItem;
2
- declare function FormItem({ label, name, children, rules }: {
3
- label: any;
4
- name: any;
5
- children: any;
6
- rules?: {};
7
- }): React.JSX.Element;
8
- declare namespace FormItem {
9
- let displayName: string;
1
+ import React, { ReactNode } from 'react';
2
+ interface FormItemProps {
3
+ label?: string;
4
+ name: string;
5
+ children: ReactNode;
6
+ className?: string;
7
+ errorKey?: string;
8
+ required?: boolean;
9
+ requiredMessage?: string;
10
+ rules?: Array<any>;
10
11
  }
11
- import React from 'react';
12
+ declare const FormItem: React.FC<FormItemProps>;
13
+ export default FormItem;
@@ -1,23 +1,30 @@
1
1
  import React, { cloneElement, isValidElement } from 'react';
2
- //* HOC's
3
- import { useFormContext } from "react-hook-form";
4
- //* Components
2
+ import lodashGet from 'lodash.get';
3
+ import classNames from 'classnames';
4
+ import { useTranslation } from '@weareconceptstudio/core';
5
5
  import ErrorMessage from '../../error-message';
6
- const FormItem = ({ label, name, children, rules = {} }) => {
7
- const { register, getValues } = useFormContext();
8
- const innerRef = register(name, rules);
9
- return (React.createElement("div", { className: "form-item" },
6
+ import { useInput } from '../hooks/useInput';
7
+ import { useRules } from '../hooks/rules';
8
+ const FormItem = ({ label, name, children, className, errorKey, required = true, requiredMessage, rules = [], }) => {
9
+ const { translate } = useTranslation();
10
+ const { formState } = useInput({
11
+ name,
12
+ rules: useRules({ rules, required, requiredMessage }),
13
+ errorKey: errorKey || label,
14
+ });
15
+ const hasError = !!lodashGet(formState.errors, name);
16
+ const classString = classNames('form-item', {
17
+ [className]: className,
18
+ 'has-error': hasError,
19
+ disabled: isValidElement(children) && children.props.disabled,
20
+ });
21
+ return (React.createElement("div", { className: classString },
10
22
  React.createElement("div", { className: "form-item-row" },
11
- React.createElement("div", { className: "form-item-label" },
12
- React.createElement("label", { htmlFor: name }, label)),
13
- React.createElement("div", { className: 'form-item-control' }, isValidElement(children) && cloneElement(children, {
14
- ref: innerRef,
15
- name,
16
- value: getValues()[name]
17
- })),
18
- React.createElement(ErrorMessage, { name: name, as: React.createElement("div", { className: 'error-message' }) }))));
23
+ label ? (React.createElement("div", { className: "form-item-label" },
24
+ React.createElement("label", { htmlFor: name, "data-required": required },
25
+ translate(label),
26
+ required ? React.createElement("span", { className: "required-symbol" }, "*") : null))) : null,
27
+ React.createElement("div", { className: "form-item-control" }, isValidElement(children) && cloneElement(children, { name })),
28
+ React.createElement(ErrorMessage, { name: name, as: React.createElement("div", { className: "error-message" }) }))));
19
29
  };
20
- if (process.env.NODE_ENV !== 'production') {
21
- FormItem.displayName = 'FormItem';
22
- }
23
30
  export default FormItem;
@@ -0,0 +1,3 @@
1
+ export function validationPatterns(type: any, pattern: any): any;
2
+ export function useRules(props: any): any[];
3
+ export function mapValidationRules(errorKey: any, rules: any): any;
@@ -0,0 +1,44 @@
1
+ import React, { useMemo } from 'react';
2
+ import { useTranslation } from '@weareconceptstudio/core';
3
+ export const validationPatterns = (type, pattern) => {
4
+ switch (type) {
5
+ case 'email':
6
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/g;
7
+ case 'number':
8
+ return /[0-9]/g;
9
+ default:
10
+ return pattern;
11
+ }
12
+ };
13
+ export const useRules = (props) => {
14
+ return useMemo(() => {
15
+ let r = [...props.rules];
16
+ if (props.required) {
17
+ r.unshift({ required: true, message: props.requiredMessage });
18
+ }
19
+ return r;
20
+ }, [props]);
21
+ };
22
+ export const mapValidationRules = (errorKey, rules) => {
23
+ const { translate } = useTranslation();
24
+ return rules?.reduce((acc, rule) => {
25
+ if (rule.required) {
26
+ acc.required = rule.message || translate('validateMessages.required', { errorKey: translate(errorKey) });
27
+ }
28
+ if (rule.pattern || rule.type) {
29
+ acc.pattern = { value: validationPatterns(rule.type, rule.pattern), message: rule.message || 'Invalid format' };
30
+ }
31
+ if (rule.minLength) {
32
+ acc.minLength = { value: rule.minLength, message: rule.message || `Minimum length is ${rule.minLength}` };
33
+ }
34
+ if (rule.maxLength) {
35
+ acc.maxLength = { value: rule.maxLength, message: rule.message || `Maximum length is ${rule.maxLength}` };
36
+ }
37
+ if (rule.validator) {
38
+ acc.validate = async (value) => {
39
+ return (await rule.validator(value)) || rule.message || 'Validation failed';
40
+ };
41
+ }
42
+ return acc;
43
+ }, {});
44
+ };
@@ -0,0 +1 @@
1
+ export declare const useEvent: <Args extends unknown[], Return>(fn: (...args: Args) => Return) => (...args: Args) => Return;
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ import { useCallback } from 'react';
3
+ const useLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
4
+ export const useEvent = (fn) => {
5
+ const ref = React.useRef(() => {
6
+ throw new Error('Cannot call an event handler while rendering.');
7
+ });
8
+ useLayoutEffect(() => {
9
+ ref.current = fn;
10
+ });
11
+ return useCallback((...args) => ref.current(...args), []);
12
+ };
@@ -2,5 +2,8 @@ import React from 'react';
2
2
  import { useFormContext } from 'react-hook-form';
3
3
  export default function useFormInstance() {
4
4
  const methods = useFormContext();
5
+ if (methods == null) {
6
+ return null;
7
+ }
5
8
  return { ...methods };
6
9
  }
@@ -0,0 +1,12 @@
1
+ export declare const useInput: (props: any) => {
2
+ field: {
3
+ value: any;
4
+ onBlur: (...args: unknown[]) => void;
5
+ onChange: (...args: any[]) => void;
6
+ disabled?: boolean;
7
+ name: any;
8
+ ref: import("react-hook-form").RefCallBack;
9
+ };
10
+ fieldState: import("react-hook-form").ControllerFieldState;
11
+ formState: import("react-hook-form").UseFormStateReturn<import("react-hook-form").FieldValues>;
12
+ };
@@ -0,0 +1,46 @@
1
+ import { useController } from 'react-hook-form';
2
+ import { useEvent } from './useEvent';
3
+ import { mapValidationRules } from './rules';
4
+ const defaultFormat = (value) => (value == null ? '' : value);
5
+ const defaultParse = (value) => (value === '' ? null : value);
6
+ export const useInput = (props) => {
7
+ const { defaultValue, name, onBlur: initialOnBlur, onChange: initialOnChange, format = defaultFormat, parse = defaultParse, multiple, errorKey, rules = [] } = props;
8
+ const { field: controllerField, fieldState, formState, } = useController({
9
+ name,
10
+ defaultValue,
11
+ rules: mapValidationRules(errorKey, rules),
12
+ });
13
+ const onBlur = useEvent((...event) => {
14
+ controllerField.onBlur();
15
+ if (initialOnBlur) {
16
+ initialOnBlur(...event);
17
+ }
18
+ });
19
+ const onChange = useEvent((...event) => {
20
+ let eventOrValue;
21
+ if (props.type == 'checkbox' && event[0]?.target?.value === 'on') {
22
+ eventOrValue = event[0].target.checked;
23
+ }
24
+ else if (props.type == 'select') {
25
+ eventOrValue = multiple ? event[0].map((ev) => ev.value) : event[0]?.value;
26
+ }
27
+ else {
28
+ eventOrValue = event[0]?.target?.value ?? event[0];
29
+ }
30
+ controllerField.onChange(parse ? parse(eventOrValue) : eventOrValue);
31
+ if (initialOnChange) {
32
+ initialOnChange(...event);
33
+ }
34
+ });
35
+ const field = {
36
+ ...controllerField,
37
+ value: format ? format(controllerField.value) : controllerField.value,
38
+ onBlur,
39
+ onChange,
40
+ };
41
+ return {
42
+ field,
43
+ fieldState,
44
+ formState,
45
+ };
46
+ };
@@ -1,18 +1,7 @@
1
+ import BaseForm from './BaseForm';
2
+ import Item from './Item';
3
+ type FormComponent<T> = typeof BaseForm & {
4
+ Item: typeof Item;
5
+ };
6
+ declare const Form: FormComponent<any>;
1
7
  export default Form;
2
- declare function Form({ initialValues: defaultValues, values, children, onSubmit, layout, mode, reValidateMode, errors, resetOptions, criteriaMode, shouldFocusError, delayError, shouldUseNativeValidation, shouldUnregister, }: {
3
- initialValues: any;
4
- values: any;
5
- children: any;
6
- onSubmit: any;
7
- layout?: string;
8
- mode?: string;
9
- reValidateMode: any;
10
- errors: any;
11
- resetOptions: any;
12
- criteriaMode: any;
13
- shouldFocusError: any;
14
- delayError: any;
15
- shouldUseNativeValidation: any;
16
- shouldUnregister: any;
17
- }): import("react").JSX.Element;
18
- declare namespace Form { }
@@ -1,5 +1,6 @@
1
- import BaseForm from "./BaseForm";
2
- import Item from "./Item";
1
+ import BaseForm from './BaseForm';
2
+ import Item from './Item';
3
+ // Create the Form object with both BaseForm and Item component
3
4
  const Form = BaseForm;
4
5
  Form.Item = Item;
5
6
  export default Form;