@contember/react-form 1.3.0-alpha.25 → 1.3.0-alpha.27
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.
- package/dist/development/components/FormCheckbox.cjs +6 -6
- package/dist/development/components/FormCheckbox.cjs.map +1 -1
- package/dist/development/components/FormCheckbox.js +6 -6
- package/dist/development/components/FormCheckbox.js.map +1 -1
- package/dist/development/components/FormInput.cjs +4 -4
- package/dist/development/components/FormInput.cjs.map +1 -1
- package/dist/development/components/FormInput.js +4 -4
- package/dist/development/components/FormInput.js.map +1 -1
- package/dist/development/hooks/useFormInputValidationHandler.cjs +15 -8
- package/dist/development/hooks/useFormInputValidationHandler.cjs.map +1 -1
- package/dist/development/hooks/useFormInputValidationHandler.js +15 -8
- package/dist/development/hooks/useFormInputValidationHandler.js.map +1 -1
- package/dist/development/internal/useFormInputHandler.cjs +22 -25
- package/dist/development/internal/useFormInputHandler.cjs.map +1 -1
- package/dist/development/internal/useFormInputHandler.js +22 -25
- package/dist/development/internal/useFormInputHandler.js.map +1 -1
- package/dist/production/components/FormCheckbox.cjs +5 -5
- package/dist/production/components/FormCheckbox.cjs.map +1 -1
- package/dist/production/components/FormCheckbox.js +5 -5
- package/dist/production/components/FormCheckbox.js.map +1 -1
- package/dist/production/components/FormInput.cjs +2 -2
- package/dist/production/components/FormInput.cjs.map +1 -1
- package/dist/production/components/FormInput.js +2 -2
- package/dist/production/components/FormInput.js.map +1 -1
- package/dist/production/hooks/useFormInputValidationHandler.cjs +15 -8
- package/dist/production/hooks/useFormInputValidationHandler.cjs.map +1 -1
- package/dist/production/hooks/useFormInputValidationHandler.js +15 -8
- package/dist/production/hooks/useFormInputValidationHandler.js.map +1 -1
- package/dist/production/internal/useFormInputHandler.cjs +22 -25
- package/dist/production/internal/useFormInputHandler.cjs.map +1 -1
- package/dist/production/internal/useFormInputHandler.js +22 -25
- package/dist/production/internal/useFormInputHandler.js.map +1 -1
- package/dist/types/components/FormError.d.ts.map +1 -1
- package/dist/types/components/FormInput.d.ts +3 -0
- package/dist/types/components/FormInput.d.ts.map +1 -1
- package/dist/types/hooks/useFormInputValidationHandler.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/internal/useFormInputHandler.d.ts +2 -6
- package/dist/types/internal/useFormInputHandler.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/types/types/index.d.ts +7 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/package.json +8 -8
- package/src/components/FormCheckbox.tsx +5 -5
- package/src/components/FormInput.tsx +5 -2
- package/src/hooks/useFormInputValidationHandler.tsx +23 -8
- package/src/index.ts +1 -0
- package/src/internal/useFormInputHandler.ts +26 -31
- package/src/types/index.ts +7 -0
|
@@ -9,11 +9,11 @@ const useFormInputHandler = require("../internal/useFormInputHandler.cjs");
|
|
|
9
9
|
const contexts = require("../contexts.cjs");
|
|
10
10
|
const useFormInputValidationHandler = require("../hooks/useFormInputValidationHandler.cjs");
|
|
11
11
|
const SlotInput = reactSlot.Slot;
|
|
12
|
-
const FormInput = reactBinding.Component(({ field, isNonbearing, defaultValue, ...props }) => {
|
|
12
|
+
const FormInput = reactBinding.Component(({ field, isNonbearing, defaultValue, formatValue: formatValueIn, parseValue: parseValueIn, ...props }) => {
|
|
13
13
|
const id = contexts.useFormFieldId();
|
|
14
14
|
const accessor = reactBinding.useField(field);
|
|
15
15
|
const errors = contexts.useFormError() ?? accessor.errors?.errors ?? [];
|
|
16
|
-
const { parseValue, formatValue, defaultInputProps } = useFormInputHandler.useFormInputHandler(accessor);
|
|
16
|
+
const { parseValue, formatValue, defaultInputProps } = useFormInputHandler.useFormInputHandler(accessor, { formatValue: formatValueIn, parseValue: parseValueIn });
|
|
17
17
|
const accessorGetter = accessor.getAccessor;
|
|
18
18
|
const { ref, onFocus, onBlur } = useFormInputValidationHandler.useFormInputValidationHandler(accessor);
|
|
19
19
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormInput.cjs","sources":["../../../src/components/FormInput.tsx"],"sourcesContent":["import * as React from 'react'\nimport { ChangeEventHandler, ComponentType, useCallback } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { Component, Field, OptionallyVariableFieldValue, SugaredRelativeSingleField, useField } from '@contember/react-binding'\nimport { dataAttribute } from '@contember/utilities'\nimport { useFormInputHandler } from '../internal/useFormInputHandler'\nimport { useFormError, useFormFieldId } from '../contexts'\nimport { useFormInputValidationHandler } from '../hooks/useFormInputValidationHandler'\n\ntype InputProps = React.JSX.IntrinsicElements['input']\nconst SlotInput = Slot as ComponentType<InputProps>\n\nexport interface FormInputProps {\n\tfield: SugaredRelativeSingleField['field']\n\tisNonbearing?: boolean\n\tdefaultValue?: OptionallyVariableFieldValue\n\tchildren: React.ReactElement\n}\n\nexport const FormInput = Component<FormInputProps>(({ field, isNonbearing, defaultValue, ...props }) => {\n\tconst id = useFormFieldId()\n\tconst accessor = useField(field)\n\tconst errors = useFormError() ?? accessor.errors?.errors ?? []\n\tconst { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor)\n\tconst accessorGetter = accessor.getAccessor\n\tconst { ref, onFocus, onBlur } = useFormInputValidationHandler(accessor)\n\n\treturn (\n\t\t<SlotInput\n\t\t\tref={ref}\n\t\t\tvalue={formatValue(accessor.value)}\n\t\t\tdata-invalid={dataAttribute(errors.length > 0)}\n\t\t\tonFocus={onFocus}\n\t\t\tonBlur={onBlur}\n\t\t\tonChange={useCallback<ChangeEventHandler<HTMLInputElement>>(e => {\n\t\t\t\taccessorGetter().updateValue(parseValue(e.target.value))\n\t\t\t}, [accessorGetter, parseValue])}\n\t\t\t{...defaultInputProps}\n\t\t\tid={id ? `${id}-input` : undefined}\n\t\t\trequired={!accessor.schema.nullable}\n\t\t\t{...props}\n\t\t/>\n\t)\n}, ({ field, isNonbearing, defaultValue }) => {\n\treturn <Field field={field} isNonbearing={isNonbearing} defaultValue={defaultValue} />\n})\n"],"names":["Slot","Component","useFormFieldId","useField","useFormError","useFormInputHandler","useFormInputValidationHandler","jsx","dataAttribute","useCallback","Field"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"FormInput.cjs","sources":["../../../src/components/FormInput.tsx"],"sourcesContent":["import * as React from 'react'\nimport { ChangeEventHandler, ComponentType, useCallback } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { Component, Field, OptionallyVariableFieldValue, SugaredRelativeSingleField, useField } from '@contember/react-binding'\nimport { dataAttribute } from '@contember/utilities'\nimport { useFormInputHandler } from '../internal/useFormInputHandler'\nimport { useFormError, useFormFieldId } from '../contexts'\nimport { useFormInputValidationHandler } from '../hooks/useFormInputValidationHandler'\nimport { FormInputHandler } from '../types'\n\ntype InputProps = React.JSX.IntrinsicElements['input']\nconst SlotInput = Slot as ComponentType<InputProps>\n\nexport interface FormInputProps {\n\tfield: SugaredRelativeSingleField['field']\n\tisNonbearing?: boolean\n\tdefaultValue?: OptionallyVariableFieldValue\n\tchildren: React.ReactElement\n\tformatValue?: FormInputHandler['formatValue']\n\tparseValue?: FormInputHandler['parseValue']\n}\n\nexport const FormInput = Component<FormInputProps>(({ field, isNonbearing, defaultValue, formatValue: formatValueIn, parseValue: parseValueIn, ...props }) => {\n\tconst id = useFormFieldId()\n\tconst accessor = useField(field)\n\tconst errors = useFormError() ?? accessor.errors?.errors ?? []\n\tconst { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor, { formatValue: formatValueIn, parseValue: parseValueIn })\n\tconst accessorGetter = accessor.getAccessor\n\tconst { ref, onFocus, onBlur } = useFormInputValidationHandler(accessor)\n\n\treturn (\n\t\t<SlotInput\n\t\t\tref={ref}\n\t\t\tvalue={formatValue(accessor.value)}\n\t\t\tdata-invalid={dataAttribute(errors.length > 0)}\n\t\t\tonFocus={onFocus}\n\t\t\tonBlur={onBlur}\n\t\t\tonChange={useCallback<ChangeEventHandler<HTMLInputElement>>(e => {\n\t\t\t\taccessorGetter().updateValue(parseValue(e.target.value))\n\t\t\t}, [accessorGetter, parseValue])}\n\t\t\t{...defaultInputProps}\n\t\t\tid={id ? `${id}-input` : undefined}\n\t\t\trequired={!accessor.schema.nullable}\n\t\t\t{...props}\n\t\t/>\n\t)\n}, ({ field, isNonbearing, defaultValue }) => {\n\treturn <Field field={field} isNonbearing={isNonbearing} defaultValue={defaultValue} />\n})\n"],"names":["Slot","Component","useFormFieldId","useField","useFormError","useFormInputHandler","useFormInputValidationHandler","jsx","dataAttribute","useCallback","Field"],"mappings":";;;;;;;;;;AAWA,MAAM,YAAYA,UAAAA;AAWX,MAAM,YAAYC,aAAA,UAA0B,CAAC,EAAE,OAAO,cAAc,cAAc,aAAa,eAAe,YAAY,cAAc,GAAG,YAAY;AAC7J,QAAM,KAAKC,SAAAA;AACL,QAAA,WAAWC,sBAAS,KAAK;AAC/B,QAAM,SAASC,SAAAA,aAAa,KAAK,SAAS,QAAQ,UAAU;AAC5D,QAAM,EAAE,YAAY,aAAa,kBAAsB,IAAAC,oBAAA,oBAAoB,UAAU,EAAE,aAAa,eAAe,YAAY,aAAc,CAAA;AAC7I,QAAM,iBAAiB,SAAS;AAChC,QAAM,EAAE,KAAK,SAAS,OAAO,IAAIC,8BAAAA,8BAA8B,QAAQ;AAGtE,SAAAC,2BAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACA;AAAA,MACA,OAAO,YAAY,SAAS,KAAK;AAAA,MACjC,gBAAcC,UAAA,cAAc,OAAO,SAAS,CAAC;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,UAAUC,MAAAA,YAAkD,CAAK,MAAA;AAChE,uBAAA,EAAiB,YAAY,WAAW,EAAE,OAAO,KAAK,CAAC;AAAA,MAAA,GACrD,CAAC,gBAAgB,UAAU,CAAC;AAAA,MAC9B,GAAG;AAAA,MACJ,IAAI,KAAK,GAAG,EAAE,WAAW;AAAA,MACzB,UAAU,CAAC,SAAS,OAAO;AAAA,MAC1B,GAAG;AAAA,IAAA;AAAA,EAAA;AAGP,GAAG,CAAC,EAAE,OAAO,cAAc,mBAAmB;AAC7C,SAAQF,2BAAAA,IAAAG,aAAAA,OAAA,EAAM,OAAc,cAA4B,aAA4B,CAAA;AACrF,CAAC;;"}
|
|
@@ -7,11 +7,11 @@ import { useFormInputHandler } from "../internal/useFormInputHandler.js";
|
|
|
7
7
|
import { useFormFieldId, useFormError } from "../contexts.js";
|
|
8
8
|
import { useFormInputValidationHandler } from "../hooks/useFormInputValidationHandler.js";
|
|
9
9
|
const SlotInput = Slot;
|
|
10
|
-
const FormInput = Component(({ field, isNonbearing, defaultValue, ...props }) => {
|
|
10
|
+
const FormInput = Component(({ field, isNonbearing, defaultValue, formatValue: formatValueIn, parseValue: parseValueIn, ...props }) => {
|
|
11
11
|
const id = useFormFieldId();
|
|
12
12
|
const accessor = useField(field);
|
|
13
13
|
const errors = useFormError() ?? accessor.errors?.errors ?? [];
|
|
14
|
-
const { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor);
|
|
14
|
+
const { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor, { formatValue: formatValueIn, parseValue: parseValueIn });
|
|
15
15
|
const accessorGetter = accessor.getAccessor;
|
|
16
16
|
const { ref, onFocus, onBlur } = useFormInputValidationHandler(accessor);
|
|
17
17
|
return /* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormInput.js","sources":["../../../src/components/FormInput.tsx"],"sourcesContent":["import * as React from 'react'\nimport { ChangeEventHandler, ComponentType, useCallback } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { Component, Field, OptionallyVariableFieldValue, SugaredRelativeSingleField, useField } from '@contember/react-binding'\nimport { dataAttribute } from '@contember/utilities'\nimport { useFormInputHandler } from '../internal/useFormInputHandler'\nimport { useFormError, useFormFieldId } from '../contexts'\nimport { useFormInputValidationHandler } from '../hooks/useFormInputValidationHandler'\n\ntype InputProps = React.JSX.IntrinsicElements['input']\nconst SlotInput = Slot as ComponentType<InputProps>\n\nexport interface FormInputProps {\n\tfield: SugaredRelativeSingleField['field']\n\tisNonbearing?: boolean\n\tdefaultValue?: OptionallyVariableFieldValue\n\tchildren: React.ReactElement\n}\n\nexport const FormInput = Component<FormInputProps>(({ field, isNonbearing, defaultValue, ...props }) => {\n\tconst id = useFormFieldId()\n\tconst accessor = useField(field)\n\tconst errors = useFormError() ?? accessor.errors?.errors ?? []\n\tconst { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor)\n\tconst accessorGetter = accessor.getAccessor\n\tconst { ref, onFocus, onBlur } = useFormInputValidationHandler(accessor)\n\n\treturn (\n\t\t<SlotInput\n\t\t\tref={ref}\n\t\t\tvalue={formatValue(accessor.value)}\n\t\t\tdata-invalid={dataAttribute(errors.length > 0)}\n\t\t\tonFocus={onFocus}\n\t\t\tonBlur={onBlur}\n\t\t\tonChange={useCallback<ChangeEventHandler<HTMLInputElement>>(e => {\n\t\t\t\taccessorGetter().updateValue(parseValue(e.target.value))\n\t\t\t}, [accessorGetter, parseValue])}\n\t\t\t{...defaultInputProps}\n\t\t\tid={id ? `${id}-input` : undefined}\n\t\t\trequired={!accessor.schema.nullable}\n\t\t\t{...props}\n\t\t/>\n\t)\n}, ({ field, isNonbearing, defaultValue }) => {\n\treturn <Field field={field} isNonbearing={isNonbearing} defaultValue={defaultValue} />\n})\n"],"names":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"FormInput.js","sources":["../../../src/components/FormInput.tsx"],"sourcesContent":["import * as React from 'react'\nimport { ChangeEventHandler, ComponentType, useCallback } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { Component, Field, OptionallyVariableFieldValue, SugaredRelativeSingleField, useField } from '@contember/react-binding'\nimport { dataAttribute } from '@contember/utilities'\nimport { useFormInputHandler } from '../internal/useFormInputHandler'\nimport { useFormError, useFormFieldId } from '../contexts'\nimport { useFormInputValidationHandler } from '../hooks/useFormInputValidationHandler'\nimport { FormInputHandler } from '../types'\n\ntype InputProps = React.JSX.IntrinsicElements['input']\nconst SlotInput = Slot as ComponentType<InputProps>\n\nexport interface FormInputProps {\n\tfield: SugaredRelativeSingleField['field']\n\tisNonbearing?: boolean\n\tdefaultValue?: OptionallyVariableFieldValue\n\tchildren: React.ReactElement\n\tformatValue?: FormInputHandler['formatValue']\n\tparseValue?: FormInputHandler['parseValue']\n}\n\nexport const FormInput = Component<FormInputProps>(({ field, isNonbearing, defaultValue, formatValue: formatValueIn, parseValue: parseValueIn, ...props }) => {\n\tconst id = useFormFieldId()\n\tconst accessor = useField(field)\n\tconst errors = useFormError() ?? accessor.errors?.errors ?? []\n\tconst { parseValue, formatValue, defaultInputProps } = useFormInputHandler(accessor, { formatValue: formatValueIn, parseValue: parseValueIn })\n\tconst accessorGetter = accessor.getAccessor\n\tconst { ref, onFocus, onBlur } = useFormInputValidationHandler(accessor)\n\n\treturn (\n\t\t<SlotInput\n\t\t\tref={ref}\n\t\t\tvalue={formatValue(accessor.value)}\n\t\t\tdata-invalid={dataAttribute(errors.length > 0)}\n\t\t\tonFocus={onFocus}\n\t\t\tonBlur={onBlur}\n\t\t\tonChange={useCallback<ChangeEventHandler<HTMLInputElement>>(e => {\n\t\t\t\taccessorGetter().updateValue(parseValue(e.target.value))\n\t\t\t}, [accessorGetter, parseValue])}\n\t\t\t{...defaultInputProps}\n\t\t\tid={id ? `${id}-input` : undefined}\n\t\t\trequired={!accessor.schema.nullable}\n\t\t\t{...props}\n\t\t/>\n\t)\n}, ({ field, isNonbearing, defaultValue }) => {\n\treturn <Field field={field} isNonbearing={isNonbearing} defaultValue={defaultValue} />\n})\n"],"names":[],"mappings":";;;;;;;;AAWA,MAAM,YAAY;AAWX,MAAM,YAAY,UAA0B,CAAC,EAAE,OAAO,cAAc,cAAc,aAAa,eAAe,YAAY,cAAc,GAAG,YAAY;AAC7J,QAAM,KAAK;AACL,QAAA,WAAW,SAAS,KAAK;AAC/B,QAAM,SAAS,aAAa,KAAK,SAAS,QAAQ,UAAU;AAC5D,QAAM,EAAE,YAAY,aAAa,kBAAsB,IAAA,oBAAoB,UAAU,EAAE,aAAa,eAAe,YAAY,aAAc,CAAA;AAC7I,QAAM,iBAAiB,SAAS;AAChC,QAAM,EAAE,KAAK,SAAS,OAAO,IAAI,8BAA8B,QAAQ;AAGtE,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACA;AAAA,MACA,OAAO,YAAY,SAAS,KAAK;AAAA,MACjC,gBAAc,cAAc,OAAO,SAAS,CAAC;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,UAAU,YAAkD,CAAK,MAAA;AAChE,uBAAA,EAAiB,YAAY,WAAW,EAAE,OAAO,KAAK,CAAC;AAAA,MAAA,GACrD,CAAC,gBAAgB,UAAU,CAAC;AAAA,MAC9B,GAAG;AAAA,MACJ,IAAI,KAAK,GAAG,EAAE,WAAW;AAAA,MACzB,UAAU,CAAC,SAAS,OAAO;AAAA,MAC1B,GAAG;AAAA,IAAA;AAAA,EAAA;AAGP,GAAG,CAAC,EAAE,OAAO,cAAc,mBAAmB;AAC7C,SAAQ,oBAAA,OAAA,EAAM,OAAc,cAA4B,aAA4B,CAAA;AACrF,CAAC;"}
|
|
@@ -36,14 +36,21 @@ const useFormInputValidationHandler = (field) => {
|
|
|
36
36
|
const input = inputRef.current;
|
|
37
37
|
const valid = input.validity?.valid;
|
|
38
38
|
const message = valid ? void 0 : input?.validationMessage;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
const previousMessage = validationMessage.current;
|
|
40
|
+
validationMessage.current = message;
|
|
41
|
+
if (!message) {
|
|
42
|
+
accessorGetter().clearErrors();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (message === previousMessage) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!field.isTouched) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!focus || !!previousMessage) {
|
|
52
|
+
accessorGetter().clearErrors();
|
|
53
|
+
accessorGetter().addError(message);
|
|
47
54
|
}
|
|
48
55
|
});
|
|
49
56
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInputValidationHandler.cjs","sources":["../../../src/hooks/useFormInputValidationHandler.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useCallback, useEffect, useRef } from 'react'\nimport { FieldAccessor, useEntityBeforePersist } from '@contember/react-binding'\n\nexport const useFormInputValidationHandler = (field: FieldAccessor<any>) => {\n\tconst accessorGetter = field.getAccessor\n\tconst validationMessage = useRef<string>()\n\tconst [focus, setFocus] = React.useState(false)\n\tconst inputRef = React.useRef<HTMLInputElement>(null)\n\tuseEntityBeforePersist(useCallback(() => {\n\t\tif (validationMessage.current) {\n\t\t\taccessorGetter().addError(validationMessage.current)\n\t\t}\n\t}, [accessorGetter]))\n\n\tuseEffect(() => {\n\t\tif (!inputRef.current) {\n\t\t\treturn\n\t\t}\n\t\tconst input = inputRef.current\n\t\tconst valid = input.validity?.valid\n\t\tconst message = valid ? undefined : input?.validationMessage\n\t\
|
|
1
|
+
{"version":3,"file":"useFormInputValidationHandler.cjs","sources":["../../../src/hooks/useFormInputValidationHandler.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useCallback, useEffect, useRef } from 'react'\nimport { FieldAccessor, useEntityBeforePersist } from '@contember/react-binding'\n\nexport const useFormInputValidationHandler = (field: FieldAccessor<any>) => {\n\tconst accessorGetter = field.getAccessor\n\tconst validationMessage = useRef<string>()\n\tconst [focus, setFocus] = React.useState(false)\n\tconst inputRef = React.useRef<HTMLInputElement>(null)\n\tuseEntityBeforePersist(useCallback(() => {\n\t\tif (validationMessage.current) {\n\t\t\taccessorGetter().addError(validationMessage.current)\n\t\t}\n\t}, [accessorGetter]))\n\n\tuseEffect(() => {\n\t\tif (!inputRef.current) {\n\t\t\treturn\n\t\t}\n\n\t\tconst input = inputRef.current\n\t\tconst valid = input.validity?.valid\n\n\t\tconst message = valid ? undefined : input?.validationMessage\n\t\tconst previousMessage = validationMessage.current\n\t\tvalidationMessage.current = message\n\n\t\t// if there is no message, we want to clear the error\n\t\tif (!message) {\n\t\t\taccessorGetter().clearErrors()\n\t\t\treturn\n\t\t}\n\t\tif (message === previousMessage) {\n\t\t\treturn\n\t\t}\n\t\t// if the input is not touched, we don't want to show the error message\n\t\tif (!field.isTouched) {\n\t\t\treturn\n\t\t}\n\n\t\t// if the input is not focused, we want to show the error message\n\t\t// also, even the input is focused, we want to replace the previous message\n\t\tif (!focus || !!previousMessage) {\n\t\t\taccessorGetter().clearErrors()\n\t\t\taccessorGetter().addError(message)\n\t\t}\n\t})\n\n\treturn {\n\t\tref: inputRef,\n\t\tonFocus: useCallback(() => {\n\t\t\tsetFocus(true)\n\t\t}, []),\n\t\tonBlur: useCallback(() => {\n\t\t\tsetFocus(false)\n\t\t\taccessorGetter().clearErrors()\n\t\t\tif (validationMessage.current) {\n\t\t\t\taccessorGetter().addError(validationMessage.current)\n\t\t\t}\n\t\t}, [accessorGetter]),\n\t}\n}\n"],"names":["useRef","React","useEntityBeforePersist","useCallback","useEffect"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAIa,MAAA,gCAAgC,CAAC,UAA8B;AAC3E,QAAM,iBAAiB,MAAM;AAC7B,QAAM,oBAAoBA,MAAAA;AAC1B,QAAM,CAAC,OAAO,QAAQ,IAAIC,iBAAM,SAAS,KAAK;AACxC,QAAA,WAAWA,iBAAM,OAAyB,IAAI;AACpDC,eAAA,uBAAuBC,kBAAY,MAAM;AACxC,QAAI,kBAAkB,SAAS;AACf,uBAAE,SAAS,kBAAkB,OAAO;AAAA,IACpD;AAAA,EAAA,GACE,CAAC,cAAc,CAAC,CAAC;AAEpBC,QAAAA,UAAU,MAAM;AACX,QAAA,CAAC,SAAS,SAAS;AACtB;AAAA,IACD;AAEA,UAAM,QAAQ,SAAS;AACjB,UAAA,QAAQ,MAAM,UAAU;AAExB,UAAA,UAAU,QAAQ,SAAY,OAAO;AAC3C,UAAM,kBAAkB,kBAAkB;AAC1C,sBAAkB,UAAU;AAG5B,QAAI,CAAC,SAAS;AACb,qBAAA,EAAiB;AACjB;AAAA,IACD;AACA,QAAI,YAAY,iBAAiB;AAChC;AAAA,IACD;AAEI,QAAA,CAAC,MAAM,WAAW;AACrB;AAAA,IACD;AAIA,QAAI,CAAC,SAAS,CAAC,CAAC,iBAAiB;AAChC,qBAAA,EAAiB;AACF,qBAAA,EAAE,SAAS,OAAO;AAAA,IAClC;AAAA,EAAA,CACA;AAEM,SAAA;AAAA,IACN,KAAK;AAAA,IACL,SAASD,kBAAY,MAAM;AAC1B,eAAS,IAAI;AAAA,IACd,GAAG,EAAE;AAAA,IACL,QAAQA,kBAAY,MAAM;AACzB,eAAS,KAAK;AACd,qBAAA,EAAiB;AACjB,UAAI,kBAAkB,SAAS;AACf,yBAAE,SAAS,kBAAkB,OAAO;AAAA,MACpD;AAAA,IAAA,GACE,CAAC,cAAc,CAAC;AAAA,EAAA;AAErB;;"}
|
|
@@ -18,14 +18,21 @@ const useFormInputValidationHandler = (field) => {
|
|
|
18
18
|
const input = inputRef.current;
|
|
19
19
|
const valid = input.validity?.valid;
|
|
20
20
|
const message = valid ? void 0 : input?.validationMessage;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
const previousMessage = validationMessage.current;
|
|
22
|
+
validationMessage.current = message;
|
|
23
|
+
if (!message) {
|
|
24
|
+
accessorGetter().clearErrors();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (message === previousMessage) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!field.isTouched) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!focus || !!previousMessage) {
|
|
34
|
+
accessorGetter().clearErrors();
|
|
35
|
+
accessorGetter().addError(message);
|
|
29
36
|
}
|
|
30
37
|
});
|
|
31
38
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInputValidationHandler.js","sources":["../../../src/hooks/useFormInputValidationHandler.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useCallback, useEffect, useRef } from 'react'\nimport { FieldAccessor, useEntityBeforePersist } from '@contember/react-binding'\n\nexport const useFormInputValidationHandler = (field: FieldAccessor<any>) => {\n\tconst accessorGetter = field.getAccessor\n\tconst validationMessage = useRef<string>()\n\tconst [focus, setFocus] = React.useState(false)\n\tconst inputRef = React.useRef<HTMLInputElement>(null)\n\tuseEntityBeforePersist(useCallback(() => {\n\t\tif (validationMessage.current) {\n\t\t\taccessorGetter().addError(validationMessage.current)\n\t\t}\n\t}, [accessorGetter]))\n\n\tuseEffect(() => {\n\t\tif (!inputRef.current) {\n\t\t\treturn\n\t\t}\n\t\tconst input = inputRef.current\n\t\tconst valid = input.validity?.valid\n\t\tconst message = valid ? undefined : input?.validationMessage\n\t\
|
|
1
|
+
{"version":3,"file":"useFormInputValidationHandler.js","sources":["../../../src/hooks/useFormInputValidationHandler.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useCallback, useEffect, useRef } from 'react'\nimport { FieldAccessor, useEntityBeforePersist } from '@contember/react-binding'\n\nexport const useFormInputValidationHandler = (field: FieldAccessor<any>) => {\n\tconst accessorGetter = field.getAccessor\n\tconst validationMessage = useRef<string>()\n\tconst [focus, setFocus] = React.useState(false)\n\tconst inputRef = React.useRef<HTMLInputElement>(null)\n\tuseEntityBeforePersist(useCallback(() => {\n\t\tif (validationMessage.current) {\n\t\t\taccessorGetter().addError(validationMessage.current)\n\t\t}\n\t}, [accessorGetter]))\n\n\tuseEffect(() => {\n\t\tif (!inputRef.current) {\n\t\t\treturn\n\t\t}\n\n\t\tconst input = inputRef.current\n\t\tconst valid = input.validity?.valid\n\n\t\tconst message = valid ? undefined : input?.validationMessage\n\t\tconst previousMessage = validationMessage.current\n\t\tvalidationMessage.current = message\n\n\t\t// if there is no message, we want to clear the error\n\t\tif (!message) {\n\t\t\taccessorGetter().clearErrors()\n\t\t\treturn\n\t\t}\n\t\tif (message === previousMessage) {\n\t\t\treturn\n\t\t}\n\t\t// if the input is not touched, we don't want to show the error message\n\t\tif (!field.isTouched) {\n\t\t\treturn\n\t\t}\n\n\t\t// if the input is not focused, we want to show the error message\n\t\t// also, even the input is focused, we want to replace the previous message\n\t\tif (!focus || !!previousMessage) {\n\t\t\taccessorGetter().clearErrors()\n\t\t\taccessorGetter().addError(message)\n\t\t}\n\t})\n\n\treturn {\n\t\tref: inputRef,\n\t\tonFocus: useCallback(() => {\n\t\t\tsetFocus(true)\n\t\t}, []),\n\t\tonBlur: useCallback(() => {\n\t\t\tsetFocus(false)\n\t\t\taccessorGetter().clearErrors()\n\t\t\tif (validationMessage.current) {\n\t\t\t\taccessorGetter().addError(validationMessage.current)\n\t\t\t}\n\t\t}, [accessorGetter]),\n\t}\n}\n"],"names":[],"mappings":";;;AAIa,MAAA,gCAAgC,CAAC,UAA8B;AAC3E,QAAM,iBAAiB,MAAM;AAC7B,QAAM,oBAAoB;AAC1B,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,KAAK;AACxC,QAAA,WAAW,MAAM,OAAyB,IAAI;AACpD,yBAAuB,YAAY,MAAM;AACxC,QAAI,kBAAkB,SAAS;AACf,uBAAE,SAAS,kBAAkB,OAAO;AAAA,IACpD;AAAA,EAAA,GACE,CAAC,cAAc,CAAC,CAAC;AAEpB,YAAU,MAAM;AACX,QAAA,CAAC,SAAS,SAAS;AACtB;AAAA,IACD;AAEA,UAAM,QAAQ,SAAS;AACjB,UAAA,QAAQ,MAAM,UAAU;AAExB,UAAA,UAAU,QAAQ,SAAY,OAAO;AAC3C,UAAM,kBAAkB,kBAAkB;AAC1C,sBAAkB,UAAU;AAG5B,QAAI,CAAC,SAAS;AACb,qBAAA,EAAiB;AACjB;AAAA,IACD;AACA,QAAI,YAAY,iBAAiB;AAChC;AAAA,IACD;AAEI,QAAA,CAAC,MAAM,WAAW;AACrB;AAAA,IACD;AAIA,QAAI,CAAC,SAAS,CAAC,CAAC,iBAAiB;AAChC,qBAAA,EAAiB;AACF,qBAAA,EAAE,SAAS,OAAO;AAAA,IAClC;AAAA,EAAA,CACA;AAEM,SAAA;AAAA,IACN,KAAK;AAAA,IACL,SAAS,YAAY,MAAM;AAC1B,eAAS,IAAI;AAAA,IACd,GAAG,EAAE;AAAA,IACL,QAAQ,YAAY,MAAM;AACzB,eAAS,KAAK;AACd,qBAAA,EAAiB;AACjB,UAAI,kBAAkB,SAAS;AACf,yBAAE,SAAS,kBAAkB,OAAO;AAAA,MACpD;AAAA,IAAA,GACE,CAAC,cAAc,CAAC;AAAA,EAAA;AAErB;"}
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const React = require("react");
|
|
4
|
-
const useFormInputHandler = (field) => {
|
|
4
|
+
const useFormInputHandler = (field, { formatValue, parseValue }) => {
|
|
5
5
|
return React.useMemo(() => {
|
|
6
6
|
const schema = field.schema;
|
|
7
7
|
const columnType = schema.type;
|
|
8
|
-
const handlerFactory = ColumnTypeHandlerFactories[columnType];
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const handlerFactory = ColumnTypeHandlerFactories[columnType] ?? defaultHandlerFactory;
|
|
9
|
+
const handler = handlerFactory(schema, field.getAccessor);
|
|
10
|
+
return {
|
|
11
|
+
defaultInputProps: handler.defaultInputProps,
|
|
12
|
+
formatValue: formatValue ?? handler.formatValue,
|
|
13
|
+
parseValue: parseValue ?? handler.parseValue
|
|
14
|
+
};
|
|
15
|
+
}, [field.getAccessor, field.schema, formatValue, parseValue]);
|
|
14
16
|
};
|
|
17
|
+
const defaultHandlerFactory = (schema, field) => ({
|
|
18
|
+
parseValue: (value) => {
|
|
19
|
+
if (value === "" && schema.nullable && field().valueOnServer === null) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
},
|
|
24
|
+
formatValue: (value) => value ?? ""
|
|
25
|
+
});
|
|
15
26
|
const ColumnTypeHandlerFactories = {
|
|
27
|
+
String: defaultHandlerFactory,
|
|
16
28
|
Integer: () => ({
|
|
17
29
|
parseValue: (value) => {
|
|
18
30
|
if (value === "") {
|
|
@@ -43,15 +55,6 @@ const ColumnTypeHandlerFactories = {
|
|
|
43
55
|
type: "number"
|
|
44
56
|
}
|
|
45
57
|
}),
|
|
46
|
-
String: (schema, field) => ({
|
|
47
|
-
parseValue: (value) => {
|
|
48
|
-
if (value === "" && schema.nullable && field().valueOnServer === null) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
return value;
|
|
52
|
-
},
|
|
53
|
-
formatValue: (value) => value ?? ""
|
|
54
|
-
}),
|
|
55
58
|
Date: () => ({
|
|
56
59
|
parseValue: (value) => {
|
|
57
60
|
if (value === "") {
|
|
@@ -84,15 +87,9 @@ const ColumnTypeHandlerFactories = {
|
|
|
84
87
|
type: "datetime-local"
|
|
85
88
|
}
|
|
86
89
|
}),
|
|
87
|
-
Bool:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Enum: () => {
|
|
91
|
-
throw new Error("Enum column type is not supported yet");
|
|
92
|
-
},
|
|
93
|
-
Uuid: () => {
|
|
94
|
-
throw new Error("UUID column type is not supported yet");
|
|
95
|
-
}
|
|
90
|
+
Bool: void 0,
|
|
91
|
+
Enum: void 0,
|
|
92
|
+
Uuid: void 0
|
|
96
93
|
};
|
|
97
94
|
const toLocalDate = (date) => {
|
|
98
95
|
const pad = (num, length = 2) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInputHandler.cjs","sources":["../../../src/internal/useFormInputHandler.ts"],"sourcesContent":["import { FieldAccessor, SchemaColumn, SchemaKnownColumnType } from '@contember/react-binding'\nimport
|
|
1
|
+
{"version":3,"file":"useFormInputHandler.cjs","sources":["../../../src/internal/useFormInputHandler.ts"],"sourcesContent":["import { FieldAccessor, SchemaColumn, SchemaKnownColumnType } from '@contember/react-binding'\nimport { useMemo } from 'react'\nimport { FormInputHandler } from '../types'\n\nexport const useFormInputHandler = (field: FieldAccessor, { formatValue, parseValue }: Partial<FormInputHandler>): FormInputHandler => {\n\treturn useMemo(() => {\n\t\tconst schema = field.schema\n\t\tconst columnType = schema.type\n\t\tconst handlerFactory = ColumnTypeHandlerFactories[columnType as SchemaKnownColumnType] ?? defaultHandlerFactory\n\t\tconst handler = handlerFactory(schema, field.getAccessor)\n\t\treturn {\n\t\t\tdefaultInputProps: handler.defaultInputProps,\n\t\t\tformatValue: formatValue ?? handler.formatValue,\n\t\t\tparseValue: parseValue ?? handler.parseValue,\n\t\t}\n\t}, [field.getAccessor, field.schema, formatValue, parseValue])\n}\n\ntype ColumnTypeHandlerFactory = (column: SchemaColumn, getAccessor: FieldAccessor.GetFieldAccessor) => FormInputHandler\n\nconst defaultHandlerFactory: ColumnTypeHandlerFactory = (schema, field) => ({\n\tparseValue: (value: string) => {\n\t\tif (value === '' && schema.nullable && field().valueOnServer === null) {\n\t\t\treturn null\n\t\t}\n\t\treturn value\n\t},\n\tformatValue: (value: string | null) => value ?? '',\n})\n\nconst ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandlerFactory | undefined> = {\n\tString: defaultHandlerFactory,\n\tInteger: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst parsed = parseInt(value, 10)\n\t\t\treturn isNaN(parsed) ? null : parsed\n\t\t},\n\t\tformatValue: (value: number | null) => {\n\t\t\treturn value === null ? '' : value.toString(10)\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'number',\n\t\t},\n\t}),\n\tDouble: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst parsed = parseFloat(value)\n\t\t\treturn isNaN(parsed) ? null : parsed\n\t\t},\n\t\tformatValue: (value: number | null) => {\n\t\t\treturn value === null ? '' : value.toString(10)\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'number',\n\t\t},\n\t}),\n\n\tDate: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst parsed = Date.parse(value)\n\t\t\treturn isNaN(parsed) ? null : (new Date(parsed)).toISOString().split('T')[0]\n\t\t},\n\t\tformatValue: (value: string | null) => {\n\t\t\tconst parsed = value ? Date.parse(value) : null\n\t\t\treturn !parsed || isNaN(parsed) ? '' : new Date(parsed).toISOString().split('T')[0]\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'date',\n\t\t},\n\t}),\n\tDateTime: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst parsed = Date.parse(value)\n\t\t\treturn isNaN(parsed) ? null : (new Date(parsed)).toISOString()\n\t\t},\n\t\tformatValue: (value: string | null) => {\n\t\t\tconst parsed = value ? Date.parse(value) : null\n\t\t\treturn !parsed || isNaN(parsed) ? '' : toLocalDate(new Date(parsed))\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'datetime-local',\n\t\t},\n\t}),\n\tBool: undefined,\n\tEnum: undefined,\n\tUuid: undefined,\n}\n\nconst toLocalDate = (date: Date) => {\n\tconst pad = (num: number, length: number = 2) => {\n\t\tconst str = num.toString()\n\t\treturn '0'.repeat(Math.max(0, length - str.length)) + str\n\t}\n\n\treturn pad(date.getFullYear(), 4) +\n\t\t'-' + pad(date.getMonth() + 1) +\n\t\t'-' + pad(date.getDate()) +\n\t\t'T' + pad(date.getHours()) +\n\t\t':' + pad(date.getMinutes()) +\n\t\t':' + pad(date.getSeconds())\n}\n"],"names":["useMemo"],"mappings":"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"}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
|
-
const useFormInputHandler = (field) => {
|
|
2
|
+
const useFormInputHandler = (field, { formatValue, parseValue }) => {
|
|
3
3
|
return useMemo(() => {
|
|
4
4
|
const schema = field.schema;
|
|
5
5
|
const columnType = schema.type;
|
|
6
|
-
const handlerFactory = ColumnTypeHandlerFactories[columnType];
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
const handlerFactory = ColumnTypeHandlerFactories[columnType] ?? defaultHandlerFactory;
|
|
7
|
+
const handler = handlerFactory(schema, field.getAccessor);
|
|
8
|
+
return {
|
|
9
|
+
defaultInputProps: handler.defaultInputProps,
|
|
10
|
+
formatValue: formatValue ?? handler.formatValue,
|
|
11
|
+
parseValue: parseValue ?? handler.parseValue
|
|
12
|
+
};
|
|
13
|
+
}, [field.getAccessor, field.schema, formatValue, parseValue]);
|
|
12
14
|
};
|
|
15
|
+
const defaultHandlerFactory = (schema, field) => ({
|
|
16
|
+
parseValue: (value) => {
|
|
17
|
+
if (value === "" && schema.nullable && field().valueOnServer === null) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
},
|
|
22
|
+
formatValue: (value) => value ?? ""
|
|
23
|
+
});
|
|
13
24
|
const ColumnTypeHandlerFactories = {
|
|
25
|
+
String: defaultHandlerFactory,
|
|
14
26
|
Integer: () => ({
|
|
15
27
|
parseValue: (value) => {
|
|
16
28
|
if (value === "") {
|
|
@@ -41,15 +53,6 @@ const ColumnTypeHandlerFactories = {
|
|
|
41
53
|
type: "number"
|
|
42
54
|
}
|
|
43
55
|
}),
|
|
44
|
-
String: (schema, field) => ({
|
|
45
|
-
parseValue: (value) => {
|
|
46
|
-
if (value === "" && schema.nullable && field().valueOnServer === null) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return value;
|
|
50
|
-
},
|
|
51
|
-
formatValue: (value) => value ?? ""
|
|
52
|
-
}),
|
|
53
56
|
Date: () => ({
|
|
54
57
|
parseValue: (value) => {
|
|
55
58
|
if (value === "") {
|
|
@@ -82,15 +85,9 @@ const ColumnTypeHandlerFactories = {
|
|
|
82
85
|
type: "datetime-local"
|
|
83
86
|
}
|
|
84
87
|
}),
|
|
85
|
-
Bool:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Enum: () => {
|
|
89
|
-
throw new Error("Enum column type is not supported yet");
|
|
90
|
-
},
|
|
91
|
-
Uuid: () => {
|
|
92
|
-
throw new Error("UUID column type is not supported yet");
|
|
93
|
-
}
|
|
88
|
+
Bool: void 0,
|
|
89
|
+
Enum: void 0,
|
|
90
|
+
Uuid: void 0
|
|
94
91
|
};
|
|
95
92
|
const toLocalDate = (date) => {
|
|
96
93
|
const pad = (num, length = 2) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInputHandler.js","sources":["../../../src/internal/useFormInputHandler.ts"],"sourcesContent":["import { FieldAccessor, SchemaColumn, SchemaKnownColumnType } from '@contember/react-binding'\nimport
|
|
1
|
+
{"version":3,"file":"useFormInputHandler.js","sources":["../../../src/internal/useFormInputHandler.ts"],"sourcesContent":["import { FieldAccessor, SchemaColumn, SchemaKnownColumnType } from '@contember/react-binding'\nimport { useMemo } from 'react'\nimport { FormInputHandler } from '../types'\n\nexport const useFormInputHandler = (field: FieldAccessor, { formatValue, parseValue }: Partial<FormInputHandler>): FormInputHandler => {\n\treturn useMemo(() => {\n\t\tconst schema = field.schema\n\t\tconst columnType = schema.type\n\t\tconst handlerFactory = ColumnTypeHandlerFactories[columnType as SchemaKnownColumnType] ?? defaultHandlerFactory\n\t\tconst handler = handlerFactory(schema, field.getAccessor)\n\t\treturn {\n\t\t\tdefaultInputProps: handler.defaultInputProps,\n\t\t\tformatValue: formatValue ?? handler.formatValue,\n\t\t\tparseValue: parseValue ?? handler.parseValue,\n\t\t}\n\t}, [field.getAccessor, field.schema, formatValue, parseValue])\n}\n\ntype ColumnTypeHandlerFactory = (column: SchemaColumn, getAccessor: FieldAccessor.GetFieldAccessor) => FormInputHandler\n\nconst defaultHandlerFactory: ColumnTypeHandlerFactory = (schema, field) => ({\n\tparseValue: (value: string) => {\n\t\tif (value === '' && schema.nullable && field().valueOnServer === null) {\n\t\t\treturn null\n\t\t}\n\t\treturn value\n\t},\n\tformatValue: (value: string | null) => value ?? '',\n})\n\nconst ColumnTypeHandlerFactories: Record<SchemaKnownColumnType, ColumnTypeHandlerFactory | undefined> = {\n\tString: defaultHandlerFactory,\n\tInteger: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst parsed = parseInt(value, 10)\n\t\t\treturn isNaN(parsed) ? null : parsed\n\t\t},\n\t\tformatValue: (value: number | null) => {\n\t\t\treturn value === null ? '' : value.toString(10)\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'number',\n\t\t},\n\t}),\n\tDouble: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst parsed = parseFloat(value)\n\t\t\treturn isNaN(parsed) ? null : parsed\n\t\t},\n\t\tformatValue: (value: number | null) => {\n\t\t\treturn value === null ? '' : value.toString(10)\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'number',\n\t\t},\n\t}),\n\n\tDate: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst parsed = Date.parse(value)\n\t\t\treturn isNaN(parsed) ? null : (new Date(parsed)).toISOString().split('T')[0]\n\t\t},\n\t\tformatValue: (value: string | null) => {\n\t\t\tconst parsed = value ? Date.parse(value) : null\n\t\t\treturn !parsed || isNaN(parsed) ? '' : new Date(parsed).toISOString().split('T')[0]\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'date',\n\t\t},\n\t}),\n\tDateTime: () => ({\n\t\tparseValue: (value: string) => {\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst parsed = Date.parse(value)\n\t\t\treturn isNaN(parsed) ? null : (new Date(parsed)).toISOString()\n\t\t},\n\t\tformatValue: (value: string | null) => {\n\t\t\tconst parsed = value ? Date.parse(value) : null\n\t\t\treturn !parsed || isNaN(parsed) ? '' : toLocalDate(new Date(parsed))\n\t\t},\n\t\tdefaultInputProps: {\n\t\t\ttype: 'datetime-local',\n\t\t},\n\t}),\n\tBool: undefined,\n\tEnum: undefined,\n\tUuid: undefined,\n}\n\nconst toLocalDate = (date: Date) => {\n\tconst pad = (num: number, length: number = 2) => {\n\t\tconst str = num.toString()\n\t\treturn '0'.repeat(Math.max(0, length - str.length)) + str\n\t}\n\n\treturn pad(date.getFullYear(), 4) +\n\t\t'-' + pad(date.getMonth() + 1) +\n\t\t'-' + pad(date.getDate()) +\n\t\t'T' + pad(date.getHours()) +\n\t\t':' + pad(date.getMinutes()) +\n\t\t':' + pad(date.getSeconds())\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormError.d.ts","sourceRoot":"","sources":["../../../src/components/FormError.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAE,SAAS,EAAW,MAAM,OAAO,CAAA;AAEtE,OAAO,EAAgB,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAEtE,eAAO,MAAM,SAAS;
|
|
1
|
+
{"version":3,"file":"FormError.d.ts","sourceRoot":"","sources":["../../../src/components/FormError.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAE,SAAS,EAAW,MAAM,OAAO,CAAA;AAEtE,OAAO,EAAgB,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAEtE,eAAO,MAAM,SAAS,4BAA6B;IAClD,SAAS,EAAE,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,SAAS,EAAE,CAAA;IACzD,QAAQ,EAAE,YAAY,CAAA;CACtB,6EAcA,CAAA"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { OptionallyVariableFieldValue, SugaredRelativeSingleField } from '@contember/react-binding';
|
|
3
|
+
import { FormInputHandler } from '../types';
|
|
3
4
|
export interface FormInputProps {
|
|
4
5
|
field: SugaredRelativeSingleField['field'];
|
|
5
6
|
isNonbearing?: boolean;
|
|
6
7
|
defaultValue?: OptionallyVariableFieldValue;
|
|
7
8
|
children: React.ReactElement;
|
|
9
|
+
formatValue?: FormInputHandler['formatValue'];
|
|
10
|
+
parseValue?: FormInputHandler['parseValue'];
|
|
8
11
|
}
|
|
9
12
|
export declare const FormInput: React.NamedExoticComponent<FormInputProps>;
|
|
10
13
|
//# sourceMappingURL=FormInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormInput.d.ts","sourceRoot":"","sources":["../../../src/components/FormInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAoB,4BAA4B,EAAE,0BAA0B,EAAY,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"FormInput.d.ts","sourceRoot":"","sources":["../../../src/components/FormInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAoB,4BAA4B,EAAE,0BAA0B,EAAY,MAAM,0BAA0B,CAAA;AAK/H,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAK3C,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,0BAA0B,CAAC,OAAO,CAAC,CAAA;IAC1C,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,YAAY,CAAC,EAAE,4BAA4B,CAAA;IAC3C,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAA;IAC5B,WAAW,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IAC7C,UAAU,CAAC,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;CAC3C;AAED,eAAO,MAAM,SAAS,4CA0BpB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInputValidationHandler.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormInputValidationHandler.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,aAAa,EAA0B,MAAM,0BAA0B,CAAA;AAEhF,eAAO,MAAM,6BAA6B,UAAW,cAAc,GAAG,CAAC;;;;
|
|
1
|
+
{"version":3,"file":"useFormInputValidationHandler.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFormInputValidationHandler.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,aAAa,EAA0B,MAAM,0BAA0B,CAAA;AAEhF,eAAO,MAAM,6BAA6B,UAAW,cAAc,GAAG,CAAC;;;;CAyDtE,CAAA"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { FieldAccessor } from '@contember/react-binding';
|
|
2
|
-
import
|
|
3
|
-
export declare const useFormInputHandler: (field: FieldAccessor) =>
|
|
4
|
-
parseValue: (value: string) => any;
|
|
5
|
-
formatValue: (value: any) => string;
|
|
6
|
-
defaultInputProps?: React.InputHTMLAttributes<HTMLInputElement> | undefined;
|
|
7
|
-
};
|
|
2
|
+
import { FormInputHandler } from '../types';
|
|
3
|
+
export declare const useFormInputHandler: (field: FieldAccessor, { formatValue, parseValue }: Partial<FormInputHandler>) => FormInputHandler;
|
|
8
4
|
//# sourceMappingURL=useFormInputHandler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormInputHandler.d.ts","sourceRoot":"","sources":["../../../src/internal/useFormInputHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAuC,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"useFormInputHandler.d.ts","sourceRoot":"","sources":["../../../src/internal/useFormInputHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAuC,MAAM,0BAA0B,CAAA;AAE7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAE3C,eAAO,MAAM,mBAAmB,UAAW,aAAa,+BAA+B,QAAQ,gBAAgB,CAAC,KAAG,gBAYlH,CAAA"}
|