@ankhorage/zora 0.5.3 → 0.6.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.
- package/CHANGELOG.md +12 -0
- package/dist/components/form/Form.d.ts +4 -0
- package/dist/components/form/Form.d.ts.map +1 -0
- package/dist/components/form/Form.js +27 -0
- package/dist/components/form/Form.js.map +1 -0
- package/dist/components/form/FormActions.d.ts +4 -0
- package/dist/components/form/FormActions.d.ts.map +1 -0
- package/dist/components/form/FormActions.js +12 -0
- package/dist/components/form/FormActions.js.map +1 -0
- package/dist/components/form/FormError.d.ts +4 -0
- package/dist/components/form/FormError.d.ts.map +1 -0
- package/dist/components/form/FormError.js +14 -0
- package/dist/components/form/FormError.js.map +1 -0
- package/dist/components/form/FormField.d.ts +4 -0
- package/dist/components/form/FormField.d.ts.map +1 -0
- package/dist/components/form/FormField.js +74 -0
- package/dist/components/form/FormField.js.map +1 -0
- package/dist/components/form/index.d.ts +8 -0
- package/dist/components/form/index.d.ts.map +1 -0
- package/dist/components/form/index.js +7 -0
- package/dist/components/form/index.js.map +1 -0
- package/dist/components/form/types.d.ts +107 -0
- package/dist/components/form/types.d.ts.map +1 -0
- package/dist/components/form/types.js +2 -0
- package/dist/components/form/types.js.map +1 -0
- package/dist/components/form/useFormController.d.ts +3 -0
- package/dist/components/form/useFormController.d.ts.map +1 -0
- package/dist/components/form/useFormController.js +62 -0
- package/dist/components/form/useFormController.js.map +1 -0
- package/dist/components/form/validation.d.ts +6 -0
- package/dist/components/form/validation.d.ts.map +1 -0
- package/dist/components/form/validation.js +52 -0
- package/dist/components/form/validation.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/patterns/auth/ForgotPasswordForm.d.ts +4 -0
- package/dist/patterns/auth/ForgotPasswordForm.d.ts.map +1 -0
- package/dist/patterns/auth/ForgotPasswordForm.js +31 -0
- package/dist/patterns/auth/ForgotPasswordForm.js.map +1 -0
- package/dist/patterns/auth/OtpForm.d.ts +4 -0
- package/dist/patterns/auth/OtpForm.d.ts.map +1 -0
- package/dist/patterns/auth/OtpForm.js +30 -0
- package/dist/patterns/auth/OtpForm.js.map +1 -0
- package/dist/patterns/auth/SignInForm.d.ts +4 -0
- package/dist/patterns/auth/SignInForm.d.ts.map +1 -0
- package/dist/patterns/auth/SignInForm.js +45 -0
- package/dist/patterns/auth/SignInForm.js.map +1 -0
- package/dist/patterns/auth/SignUpForm.d.ts +4 -0
- package/dist/patterns/auth/SignUpForm.d.ts.map +1 -0
- package/dist/patterns/auth/SignUpForm.js +37 -0
- package/dist/patterns/auth/SignUpForm.js.map +1 -0
- package/dist/patterns/auth/index.d.ts +6 -0
- package/dist/patterns/auth/index.d.ts.map +1 -0
- package/dist/patterns/auth/index.js +5 -0
- package/dist/patterns/auth/index.js.map +1 -0
- package/dist/patterns/auth/types.d.ts +57 -0
- package/dist/patterns/auth/types.d.ts.map +1 -0
- package/dist/patterns/auth/types.js +2 -0
- package/dist/patterns/auth/types.js.map +1 -0
- package/dist/patterns/auth/utils.d.ts +8 -0
- package/dist/patterns/auth/utils.d.ts.map +1 -0
- package/dist/patterns/auth/utils.js +51 -0
- package/dist/patterns/auth/utils.js.map +1 -0
- package/package.json +2 -2
- package/src/components/form/Form.tsx +61 -0
- package/src/components/form/FormActions.tsx +23 -0
- package/src/components/form/FormError.tsx +20 -0
- package/src/components/form/FormField.tsx +128 -0
- package/src/components/form/index.ts +24 -0
- package/src/components/form/types.ts +115 -0
- package/src/components/form/useFormController.ts +105 -0
- package/src/components/form/validation.test.ts +79 -0
- package/src/components/form/validation.ts +83 -0
- package/src/index.ts +43 -2
- package/src/patterns/auth/ForgotPasswordForm.tsx +84 -0
- package/src/patterns/auth/OtpForm.tsx +80 -0
- package/src/patterns/auth/SignInForm.tsx +111 -0
- package/src/patterns/auth/SignUpForm.tsx +76 -0
- package/src/patterns/auth/index.ts +17 -0
- package/src/patterns/auth/types.ts +67 -0
- package/src/patterns/auth/utils.ts +80 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 67b131e: Approved with amendments.
|
|
8
|
+
|
|
9
|
+
## 0.6.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- ab9fc54: Add provider-agnostic form primitives and auth form patterns for sign-in, sign-up, password reset, and OTP flows.
|
|
14
|
+
|
|
3
15
|
## 0.5.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FormProps } from './types';
|
|
3
|
+
export declare function Form<TName extends string = string>({ fields, values, onChange, onSubmit, errors, error, loading, disabled, submitLabel, actions, footer, validateOnChange, testID, }: FormProps<TName>): React.JSX.Element;
|
|
4
|
+
//# sourceMappingURL=Form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/form/Form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,wBAAgB,IAAI,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,EAClD,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,KAAK,EACL,OAAe,EACf,QAAgB,EAChB,WAAsB,EACtB,OAAO,EACP,MAAM,EACN,gBAAwB,EACxB,MAAM,GACP,EAAE,SAAS,CAAC,KAAK,CAAC,qBAqClB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Box, Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { FormActions } from './FormActions';
|
|
4
|
+
import { FormError } from './FormError';
|
|
5
|
+
import { FormField } from './FormField';
|
|
6
|
+
import { useFormController } from './useFormController';
|
|
7
|
+
export function Form({ fields, values, onChange, onSubmit, errors, error, loading = false, disabled = false, submitLabel = 'Submit', actions, footer, validateOnChange = false, testID, }) {
|
|
8
|
+
const controller = useFormController({
|
|
9
|
+
fields,
|
|
10
|
+
values,
|
|
11
|
+
errors,
|
|
12
|
+
onChange,
|
|
13
|
+
onSubmit,
|
|
14
|
+
validateOnChange,
|
|
15
|
+
});
|
|
16
|
+
return (<Stack gap="m" testID={testID}>
|
|
17
|
+
<FormError error={error}/>
|
|
18
|
+
{fields.map((field) => (<FormField key={field.name} disabled={disabled} error={controller.errors[field.name]} field={field} loading={loading} onChange={controller.setFieldValue} value={values[field.name]}/>))}
|
|
19
|
+
<FormActions disabled={disabled} loading={loading} onSubmit={() => {
|
|
20
|
+
void controller.handleSubmit();
|
|
21
|
+
}} submitLabel={submitLabel}>
|
|
22
|
+
{actions}
|
|
23
|
+
</FormActions>
|
|
24
|
+
{footer ? <Box>{footer}</Box> : null}
|
|
25
|
+
</Stack>);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=Form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Form.js","sourceRoot":"","sources":["../../../src/components/form/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,UAAU,IAAI,CAAgC,EAClD,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,KAAK,EACL,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,QAAQ,EACtB,OAAO,EACP,MAAM,EACN,gBAAgB,GAAG,KAAK,EACxB,MAAM,GACW;IACjB,MAAM,UAAU,GAAG,iBAAiB,CAAC;QACnC,MAAM;QACN,MAAM;QACN,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,gBAAgB;KACjB,CAAC,CAAC;IAEH,OAAO,CACL,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAC5B;MAAA,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EACxB;MAAA,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,CAAC,SAAS,CACR,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAChB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CACrC,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CACnC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAC1B,CACH,CAAC,CACF;MAAA,CAAC,WAAW,CACV,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,GAAG,EAAE;YACb,KAAK,UAAU,CAAC,YAAY,EAAE,CAAC;QACjC,CAAC,CAAC,CACF,WAAW,CAAC,CAAC,WAAW,CAAC,CAEzB;QAAA,CAAC,OAAO,CACV;MAAA,EAAE,WAAW,CACb;MAAA,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CACtC;IAAA,EAAE,KAAK,CAAC,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Stack } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { FormActions } from './FormActions';\nimport { FormError } from './FormError';\nimport { FormField } from './FormField';\nimport type { FormProps } from './types';\nimport { useFormController } from './useFormController';\n\nexport function Form<TName extends string = string>({\n fields,\n values,\n onChange,\n onSubmit,\n errors,\n error,\n loading = false,\n disabled = false,\n submitLabel = 'Submit',\n actions,\n footer,\n validateOnChange = false,\n testID,\n}: FormProps<TName>) {\n const controller = useFormController({\n fields,\n values,\n errors,\n onChange,\n onSubmit,\n validateOnChange,\n });\n\n return (\n <Stack gap=\"m\" testID={testID}>\n <FormError error={error} />\n {fields.map((field) => (\n <FormField\n key={field.name}\n disabled={disabled}\n error={controller.errors[field.name]}\n field={field}\n loading={loading}\n onChange={controller.setFieldValue}\n value={values[field.name]}\n />\n ))}\n <FormActions\n disabled={disabled}\n loading={loading}\n onSubmit={() => {\n void controller.handleSubmit();\n }}\n submitLabel={submitLabel}\n >\n {actions}\n </FormActions>\n {footer ? <Box>{footer}</Box> : null}\n </Stack>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormActions.d.ts","sourceRoot":"","sources":["../../../src/components/form/FormActions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,wBAAgB,WAAW,CAAC,EAC1B,WAAsB,EACtB,OAAe,EACf,QAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,MAAM,GACP,EAAE,gBAAgB,qBASlB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Box, Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Button } from '../button';
|
|
4
|
+
export function FormActions({ submitLabel = 'Submit', loading = false, disabled = false, onSubmit, children, testID, }) {
|
|
5
|
+
return (<Stack gap="s" testID={testID}>
|
|
6
|
+
<Button disabled={disabled} fullWidth loading={loading} onPress={onSubmit}>
|
|
7
|
+
{submitLabel}
|
|
8
|
+
</Button>
|
|
9
|
+
{children ? <Box>{children}</Box> : null}
|
|
10
|
+
</Stack>);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=FormActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormActions.js","sourceRoot":"","sources":["../../../src/components/form/FormActions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGnC,MAAM,UAAU,WAAW,CAAC,EAC1B,WAAW,GAAG,QAAQ,EACtB,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,QAAQ,EACR,QAAQ,EACR,MAAM,GACW;IACjB,OAAO,CACL,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAC5B;MAAA,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CACxE;QAAA,CAAC,WAAW,CACd;MAAA,EAAE,MAAM,CACR;MAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAC1C;IAAA,EAAE,KAAK,CAAC,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Stack } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Button } from '../button';\nimport type { FormActionsProps } from './types';\n\nexport function FormActions({\n submitLabel = 'Submit',\n loading = false,\n disabled = false,\n onSubmit,\n children,\n testID,\n}: FormActionsProps) {\n return (\n <Stack gap=\"s\" testID={testID}>\n <Button disabled={disabled} fullWidth loading={loading} onPress={onSubmit}>\n {submitLabel}\n </Button>\n {children ? <Box>{children}</Box> : null}\n </Stack>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormError.d.ts","sourceRoot":"","sources":["../../../src/components/form/FormError.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,cAAc,4BAc1D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Box, Text, useTheme } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export function FormError({ error, testID }) {
|
|
4
|
+
const { theme } = useTheme();
|
|
5
|
+
if (!error) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
return (<Box borderColor={theme.colors.error} borderWidth={1} p="s" radius="m" testID={testID}>
|
|
9
|
+
<Text color={theme.colors.error} variant="bodySmall">
|
|
10
|
+
{error}
|
|
11
|
+
</Text>
|
|
12
|
+
</Box>);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=FormError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormError.js","sourceRoot":"","sources":["../../../src/components/form/FormError.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAkB;IACzD,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CACpF;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,CAClD;QAAA,CAAC,KAAK,CACR;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Text, useTheme } from '@ankhorage/surface';\nimport React from 'react';\n\nimport type { FormErrorProps } from './types';\n\nexport function FormError({ error, testID }: FormErrorProps) {\n const { theme } = useTheme();\n\n if (!error) {\n return null;\n }\n\n return (\n <Box borderColor={theme.colors.error} borderWidth={1} p=\"s\" radius=\"m\" testID={testID}>\n <Text color={theme.colors.error} variant=\"bodySmall\">\n {error}\n </Text>\n </Box>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../../src/components/form/FormField.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAA0C,cAAc,EAAE,MAAM,SAAS,CAAC;AAgFtF,wBAAgB,SAAS,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,qBA2CpF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Field, Stack, Text } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Input } from '../input';
|
|
4
|
+
import { hasRequiredRule } from './validation';
|
|
5
|
+
function isControlFieldProps(props) {
|
|
6
|
+
return 'field' in props;
|
|
7
|
+
}
|
|
8
|
+
function resolveKeyboardType(field) {
|
|
9
|
+
if (field.keyboardType) {
|
|
10
|
+
return field.keyboardType;
|
|
11
|
+
}
|
|
12
|
+
if (field.type === 'email') {
|
|
13
|
+
return 'email-address';
|
|
14
|
+
}
|
|
15
|
+
if (field.type === 'number' || field.type === 'otp') {
|
|
16
|
+
return 'number-pad';
|
|
17
|
+
}
|
|
18
|
+
if (field.type === 'tel') {
|
|
19
|
+
return 'phone-pad';
|
|
20
|
+
}
|
|
21
|
+
if (field.type === 'url') {
|
|
22
|
+
return 'url';
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
function resolveAutoCapitalize(field) {
|
|
27
|
+
if (field.autoCapitalize) {
|
|
28
|
+
return field.autoCapitalize;
|
|
29
|
+
}
|
|
30
|
+
if (['email', 'password', 'url'].includes(field.type ?? 'text')) {
|
|
31
|
+
return 'none';
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
function resolveTextContentType(field) {
|
|
36
|
+
if (field.textContentType) {
|
|
37
|
+
return field.textContentType;
|
|
38
|
+
}
|
|
39
|
+
if (field.type === 'email') {
|
|
40
|
+
return 'emailAddress';
|
|
41
|
+
}
|
|
42
|
+
if (field.type === 'password') {
|
|
43
|
+
return 'password';
|
|
44
|
+
}
|
|
45
|
+
if (field.type === 'otp') {
|
|
46
|
+
return 'oneTimeCode';
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
function renderLabel(label, description) {
|
|
51
|
+
return (<Stack gap="xs">
|
|
52
|
+
<Text variant="label" weight="semiBold">
|
|
53
|
+
{label}
|
|
54
|
+
</Text>
|
|
55
|
+
{description ? (<Text tone="muted" variant="bodySmall">
|
|
56
|
+
{description}
|
|
57
|
+
</Text>) : null}
|
|
58
|
+
</Stack>);
|
|
59
|
+
}
|
|
60
|
+
export function FormField(props) {
|
|
61
|
+
if (!isControlFieldProps(props)) {
|
|
62
|
+
const { label, description, helperText, children, ...fieldProps } = props;
|
|
63
|
+
return (<Field {...fieldProps} helperText={helperText} label={renderLabel(label, description)}>
|
|
64
|
+
{children}
|
|
65
|
+
</Field>);
|
|
66
|
+
}
|
|
67
|
+
const { field, value, error, disabled = false, loading = false, onChange, testID } = props;
|
|
68
|
+
const fieldDisabled = disabled || loading || field.disabled;
|
|
69
|
+
const required = field.required ?? hasRequiredRule(field.rules);
|
|
70
|
+
return (<Field disabled={fieldDisabled} errorText={error} helperText={field.helperText} invalid={Boolean(error)} label={renderLabel(field.label, field.description)} readOnly={field.readOnly} required={required} testID={testID ?? field.testID}>
|
|
71
|
+
<Input accessibilityLabel={typeof field.label === 'string' ? field.label : undefined} autoCapitalize={resolveAutoCapitalize(field)} autoComplete={field.autoComplete} disabled={fieldDisabled} invalid={Boolean(error)} keyboardType={resolveKeyboardType(field)} maxLength={field.maxLength} onChangeText={(nextValue) => onChange(field.name, nextValue)} placeholder={field.placeholder} readOnly={field.readOnly} secureTextEntry={field.secureTextEntry ?? field.type === 'password'} textContentType={resolveTextContentType(field)} value={value}/>
|
|
72
|
+
</Field>);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=FormField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormField.js","sourceRoot":"","sources":["../../../src/components/form/FormField.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Field, Stack, Text } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Input } from '../input';\nimport type { FormFieldConfig, FormFieldControlProps, FormFieldProps } from './types';\nimport { hasRequiredRule } from './validation';\n\nfunction isControlFieldProps<TName extends string>(\n props: FormFieldProps<TName>,\n): props is FormFieldControlProps<TName> {\n return 'field' in props;\n}\n\nfunction resolveKeyboardType(field: FormFieldConfig) {\n if (field.keyboardType) {\n return field.keyboardType;\n }\n\n if (field.type === 'email') {\n return 'email-address';\n }\n\n if (field.type === 'number' || field.type === 'otp') {\n return 'number-pad';\n }\n\n if (field.type === 'tel') {\n return 'phone-pad';\n }\n\n if (field.type === 'url') {\n return 'url';\n }\n\n return undefined;\n}\n\nfunction resolveAutoCapitalize(field: FormFieldConfig) {\n if (field.autoCapitalize) {\n return field.autoCapitalize;\n }\n\n if (['email', 'password', 'url'].includes(field.type ?? 'text')) {\n return 'none';\n }\n\n return undefined;\n}\n\nfunction resolveTextContentType(field: FormFieldConfig) {\n if (field.textContentType) {\n return field.textContentType;\n }\n\n if (field.type === 'email') {\n return 'emailAddress';\n }\n\n if (field.type === 'password') {\n return 'password';\n }\n\n if (field.type === 'otp') {\n return 'oneTimeCode';\n }\n\n return undefined;\n}\n\nfunction renderLabel(label: React.ReactNode, description: React.ReactNode | undefined) {\n return (\n <Stack gap=\"xs\">\n <Text variant=\"label\" weight=\"semiBold\">\n {label}\n </Text>\n {description ? (\n <Text tone=\"muted\" variant=\"bodySmall\">\n {description}\n </Text>\n ) : null}\n </Stack>\n );\n}\n\nexport function FormField<TName extends string = string>(props: FormFieldProps<TName>) {\n if (!isControlFieldProps(props)) {\n const { label, description, helperText, children, ...fieldProps } = props;\n\n return (\n <Field {...fieldProps} helperText={helperText} label={renderLabel(label, description)}>\n {children}\n </Field>\n );\n }\n\n const { field, value, error, disabled = false, loading = false, onChange, testID } = props;\n const fieldDisabled = disabled || loading || field.disabled;\n const required = field.required ?? hasRequiredRule(field.rules);\n\n return (\n <Field\n disabled={fieldDisabled}\n errorText={error}\n helperText={field.helperText}\n invalid={Boolean(error)}\n label={renderLabel(field.label, field.description)}\n readOnly={field.readOnly}\n required={required}\n testID={testID ?? field.testID}\n >\n <Input\n accessibilityLabel={typeof field.label === 'string' ? field.label : undefined}\n autoCapitalize={resolveAutoCapitalize(field)}\n autoComplete={field.autoComplete}\n disabled={fieldDisabled}\n invalid={Boolean(error)}\n keyboardType={resolveKeyboardType(field)}\n maxLength={field.maxLength}\n onChangeText={(nextValue) => onChange(field.name, nextValue)}\n placeholder={field.placeholder}\n readOnly={field.readOnly}\n secureTextEntry={field.secureTextEntry ?? field.type === 'password'}\n textContentType={resolveTextContentType(field)}\n value={value}\n />\n </Field>\n );\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Form } from './Form';
|
|
2
|
+
export { FormActions } from './FormActions';
|
|
3
|
+
export { FormError } from './FormError';
|
|
4
|
+
export { FormField } from './FormField';
|
|
5
|
+
export type { FormActionsProps, FormErrorProps, FormErrors, FormFieldConfig, FormFieldControlProps, FormFieldInputType, FormFieldProps, FormFieldValue, FormFieldWrapperProps, FormProps, FormValidationErrors, FormValidationResult, FormValues, UseFormControllerOptions, UseFormControllerResult, ValidationRule, } from './types';
|
|
6
|
+
export { useFormController } from './useFormController';
|
|
7
|
+
export { hasRequiredRule, validateField, validateFields, validateValue } from './validation';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/form/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,SAAS,EACT,oBAAoB,EACpB,oBAAoB,EACpB,UAAU,EACV,wBAAwB,EACxB,uBAAuB,EACvB,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Form } from './Form';
|
|
2
|
+
export { FormActions } from './FormActions';
|
|
3
|
+
export { FormError } from './FormError';
|
|
4
|
+
export { FormField } from './FormField';
|
|
5
|
+
export { useFormController } from './useFormController';
|
|
6
|
+
export { hasRequiredRule, validateField, validateFields, validateValue } from './validation';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/form/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAmBxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { Form } from './Form';\nexport { FormActions } from './FormActions';\nexport { FormError } from './FormError';\nexport { FormField } from './FormField';\nexport type {\n FormActionsProps,\n FormErrorProps,\n FormErrors,\n FormFieldConfig,\n FormFieldControlProps,\n FormFieldInputType,\n FormFieldProps,\n FormFieldValue,\n FormFieldWrapperProps,\n FormProps,\n FormValidationErrors,\n FormValidationResult,\n FormValues,\n UseFormControllerOptions,\n UseFormControllerResult,\n ValidationRule,\n} from './types';\nexport { useFormController } from './useFormController';\nexport { hasRequiredRule, validateField, validateFields, validateValue } from './validation';\n"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { FieldProps as SurfaceFieldProps } from '@ankhorage/surface';
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
import type { InputProps } from '../input';
|
|
4
|
+
export type ValidationRule = {
|
|
5
|
+
kind: 'required';
|
|
6
|
+
message?: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'email';
|
|
9
|
+
message?: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'minLength';
|
|
12
|
+
value: number;
|
|
13
|
+
message?: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'pattern';
|
|
16
|
+
value: string;
|
|
17
|
+
message?: string;
|
|
18
|
+
};
|
|
19
|
+
export type FormFieldValue = string;
|
|
20
|
+
export type FormValues<TName extends string = string> = Record<TName, FormFieldValue>;
|
|
21
|
+
export type FormErrors<TName extends string = string> = Partial<Record<TName, React.ReactNode>>;
|
|
22
|
+
export type FormValidationErrors<TName extends string = string> = Partial<Record<TName, string>>;
|
|
23
|
+
export type FormFieldInputType = 'email' | 'number' | 'otp' | 'password' | 'tel' | 'text' | 'url';
|
|
24
|
+
export interface FormFieldConfig<TName extends string = string> {
|
|
25
|
+
name: TName;
|
|
26
|
+
label: React.ReactNode;
|
|
27
|
+
description?: React.ReactNode;
|
|
28
|
+
helperText?: React.ReactNode;
|
|
29
|
+
type?: FormFieldInputType;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
rules?: readonly ValidationRule[];
|
|
32
|
+
autoCapitalize?: InputProps['autoCapitalize'];
|
|
33
|
+
autoComplete?: InputProps['autoComplete'];
|
|
34
|
+
keyboardType?: InputProps['keyboardType'];
|
|
35
|
+
maxLength?: InputProps['maxLength'];
|
|
36
|
+
readOnly?: boolean;
|
|
37
|
+
required?: boolean;
|
|
38
|
+
secureTextEntry?: boolean;
|
|
39
|
+
textContentType?: InputProps['textContentType'];
|
|
40
|
+
disabled?: boolean;
|
|
41
|
+
testID?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface FormFieldWrapperProps extends Pick<SurfaceFieldProps, 'children' | 'disabled' | 'errorText' | 'invalid' | 'readOnly' | 'required' | 'testID'> {
|
|
44
|
+
label: React.ReactNode;
|
|
45
|
+
description?: React.ReactNode;
|
|
46
|
+
helperText?: React.ReactNode;
|
|
47
|
+
}
|
|
48
|
+
export interface FormFieldControlProps<TName extends string = string> {
|
|
49
|
+
field: FormFieldConfig<TName>;
|
|
50
|
+
value: FormFieldValue;
|
|
51
|
+
onChange: (name: TName, value: FormFieldValue) => void;
|
|
52
|
+
error?: React.ReactNode;
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
loading?: boolean;
|
|
55
|
+
testID?: string;
|
|
56
|
+
}
|
|
57
|
+
export type FormFieldProps<TName extends string = string> = FormFieldControlProps<TName> | FormFieldWrapperProps;
|
|
58
|
+
export interface FormActionsProps {
|
|
59
|
+
submitLabel?: React.ReactNode;
|
|
60
|
+
loading?: boolean;
|
|
61
|
+
disabled?: boolean;
|
|
62
|
+
onSubmit?: () => void;
|
|
63
|
+
children?: React.ReactNode;
|
|
64
|
+
testID?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface FormErrorProps {
|
|
67
|
+
error?: React.ReactNode;
|
|
68
|
+
testID?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface FormProps<TName extends string = string> {
|
|
71
|
+
fields: readonly FormFieldConfig<TName>[];
|
|
72
|
+
values: FormValues<TName>;
|
|
73
|
+
onChange: (values: FormValues<TName>) => void;
|
|
74
|
+
onSubmit: (values: FormValues<TName>) => void | Promise<void>;
|
|
75
|
+
errors?: FormErrors<TName>;
|
|
76
|
+
error?: React.ReactNode;
|
|
77
|
+
loading?: boolean;
|
|
78
|
+
disabled?: boolean;
|
|
79
|
+
submitLabel?: React.ReactNode;
|
|
80
|
+
actions?: React.ReactNode;
|
|
81
|
+
footer?: React.ReactNode;
|
|
82
|
+
validateOnChange?: boolean;
|
|
83
|
+
testID?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface FormValidationResult<TName extends string = string> {
|
|
86
|
+
errors: FormValidationErrors<TName>;
|
|
87
|
+
valid: boolean;
|
|
88
|
+
}
|
|
89
|
+
export interface UseFormControllerOptions<TName extends string = string> {
|
|
90
|
+
fields: readonly FormFieldConfig<TName>[];
|
|
91
|
+
initialValues?: Partial<FormValues<TName>>;
|
|
92
|
+
values?: FormValues<TName>;
|
|
93
|
+
errors?: FormErrors<TName>;
|
|
94
|
+
onChange?: (values: FormValues<TName>) => void;
|
|
95
|
+
onSubmit?: (values: FormValues<TName>) => void | Promise<void>;
|
|
96
|
+
validateOnChange?: boolean;
|
|
97
|
+
}
|
|
98
|
+
export interface UseFormControllerResult<TName extends string = string> {
|
|
99
|
+
values: FormValues<TName>;
|
|
100
|
+
errors: FormErrors<TName>;
|
|
101
|
+
setValues: (values: FormValues<TName>) => void;
|
|
102
|
+
setFieldValue: (name: TName, value: FormFieldValue) => void;
|
|
103
|
+
validate: () => FormValidationResult<TName>;
|
|
104
|
+
handleSubmit: () => Promise<void>;
|
|
105
|
+
reset: () => void;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/form/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/form/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { FieldProps as SurfaceFieldProps } from '@ankhorage/surface';\nimport type React from 'react';\n\nimport type { InputProps } from '../input';\n\nexport type ValidationRule =\n | { kind: 'required'; message?: string }\n | { kind: 'email'; message?: string }\n | { kind: 'minLength'; value: number; message?: string }\n | { kind: 'pattern'; value: string; message?: string };\n\nexport type FormFieldValue = string;\nexport type FormValues<TName extends string = string> = Record<TName, FormFieldValue>;\nexport type FormErrors<TName extends string = string> = Partial<Record<TName, React.ReactNode>>;\nexport type FormValidationErrors<TName extends string = string> = Partial<Record<TName, string>>;\n\nexport type FormFieldInputType = 'email' | 'number' | 'otp' | 'password' | 'tel' | 'text' | 'url';\n\nexport interface FormFieldConfig<TName extends string = string> {\n name: TName;\n label: React.ReactNode;\n description?: React.ReactNode;\n helperText?: React.ReactNode;\n type?: FormFieldInputType;\n placeholder?: string;\n rules?: readonly ValidationRule[];\n autoCapitalize?: InputProps['autoCapitalize'];\n autoComplete?: InputProps['autoComplete'];\n keyboardType?: InputProps['keyboardType'];\n maxLength?: InputProps['maxLength'];\n readOnly?: boolean;\n required?: boolean;\n secureTextEntry?: boolean;\n textContentType?: InputProps['textContentType'];\n disabled?: boolean;\n testID?: string;\n}\n\nexport interface FormFieldWrapperProps extends Pick<\n SurfaceFieldProps,\n 'children' | 'disabled' | 'errorText' | 'invalid' | 'readOnly' | 'required' | 'testID'\n> {\n label: React.ReactNode;\n description?: React.ReactNode;\n helperText?: React.ReactNode;\n}\n\nexport interface FormFieldControlProps<TName extends string = string> {\n field: FormFieldConfig<TName>;\n value: FormFieldValue;\n onChange: (name: TName, value: FormFieldValue) => void;\n error?: React.ReactNode;\n disabled?: boolean;\n loading?: boolean;\n testID?: string;\n}\n\nexport type FormFieldProps<TName extends string = string> =\n | FormFieldControlProps<TName>\n | FormFieldWrapperProps;\n\nexport interface FormActionsProps {\n submitLabel?: React.ReactNode;\n loading?: boolean;\n disabled?: boolean;\n onSubmit?: () => void;\n children?: React.ReactNode;\n testID?: string;\n}\n\nexport interface FormErrorProps {\n error?: React.ReactNode;\n testID?: string;\n}\n\nexport interface FormProps<TName extends string = string> {\n fields: readonly FormFieldConfig<TName>[];\n values: FormValues<TName>;\n onChange: (values: FormValues<TName>) => void;\n onSubmit: (values: FormValues<TName>) => void | Promise<void>;\n errors?: FormErrors<TName>;\n error?: React.ReactNode;\n loading?: boolean;\n disabled?: boolean;\n submitLabel?: React.ReactNode;\n actions?: React.ReactNode;\n footer?: React.ReactNode;\n validateOnChange?: boolean;\n testID?: string;\n}\n\nexport interface FormValidationResult<TName extends string = string> {\n errors: FormValidationErrors<TName>;\n valid: boolean;\n}\n\nexport interface UseFormControllerOptions<TName extends string = string> {\n fields: readonly FormFieldConfig<TName>[];\n initialValues?: Partial<FormValues<TName>>;\n values?: FormValues<TName>;\n errors?: FormErrors<TName>;\n onChange?: (values: FormValues<TName>) => void;\n onSubmit?: (values: FormValues<TName>) => void | Promise<void>;\n validateOnChange?: boolean;\n}\n\nexport interface UseFormControllerResult<TName extends string = string> {\n values: FormValues<TName>;\n errors: FormErrors<TName>;\n setValues: (values: FormValues<TName>) => void;\n setFieldValue: (name: TName, value: FormFieldValue) => void;\n validate: () => FormValidationResult<TName>;\n handleSubmit: () => Promise<void>;\n reset: () => void;\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { UseFormControllerOptions, UseFormControllerResult } from './types';
|
|
2
|
+
export declare function useFormController<TName extends string = string>({ fields, initialValues, values: controlledValues, errors: externalErrors, onChange, onSubmit, validateOnChange, }: UseFormControllerOptions<TName>): UseFormControllerResult<TName>;
|
|
3
|
+
//# sourceMappingURL=useFormController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormController.d.ts","sourceRoot":"","sources":["../../../src/components/form/useFormController.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAejB,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,EAC/D,MAAM,EACN,aAAa,EACb,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,cAAc,EACtB,QAAQ,EACR,QAAQ,EACR,gBAAwB,GACzB,EAAE,wBAAwB,CAAC,KAAK,CAAC,GAAG,uBAAuB,CAAC,KAAK,CAAC,CA0ElE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { validateFields } from './validation';
|
|
3
|
+
function createInitialValues(fields, initialValues) {
|
|
4
|
+
const values = fields.reduce((nextValues, field) => {
|
|
5
|
+
nextValues[field.name] = initialValues?.[field.name] ?? '';
|
|
6
|
+
return nextValues;
|
|
7
|
+
}, {});
|
|
8
|
+
return values;
|
|
9
|
+
}
|
|
10
|
+
export function useFormController({ fields, initialValues, values: controlledValues, errors: externalErrors, onChange, onSubmit, validateOnChange = false, }) {
|
|
11
|
+
const initialValuesRef = React.useRef(createInitialValues(fields, initialValues));
|
|
12
|
+
const [internalValues, setInternalValues] = React.useState(initialValuesRef.current);
|
|
13
|
+
const [validationErrors, setValidationErrors] = React.useState({});
|
|
14
|
+
const values = controlledValues ?? internalValues;
|
|
15
|
+
const errors = React.useMemo(() => ({
|
|
16
|
+
...validationErrors,
|
|
17
|
+
...externalErrors,
|
|
18
|
+
}), [externalErrors, validationErrors]);
|
|
19
|
+
const setValues = React.useCallback((nextValues) => {
|
|
20
|
+
if (!controlledValues) {
|
|
21
|
+
setInternalValues(nextValues);
|
|
22
|
+
}
|
|
23
|
+
onChange?.(nextValues);
|
|
24
|
+
}, [controlledValues, onChange]);
|
|
25
|
+
const validate = React.useCallback(() => {
|
|
26
|
+
const result = validateFields(fields, values);
|
|
27
|
+
setValidationErrors(result.errors);
|
|
28
|
+
return result;
|
|
29
|
+
}, [fields, values]);
|
|
30
|
+
const setFieldValue = React.useCallback((name, value) => {
|
|
31
|
+
const nextValues = {
|
|
32
|
+
...values,
|
|
33
|
+
[name]: value,
|
|
34
|
+
};
|
|
35
|
+
setValues(nextValues);
|
|
36
|
+
if (validateOnChange) {
|
|
37
|
+
const result = validateFields(fields, nextValues);
|
|
38
|
+
setValidationErrors(result.errors);
|
|
39
|
+
}
|
|
40
|
+
}, [fields, setValues, validateOnChange, values]);
|
|
41
|
+
const handleSubmit = React.useCallback(async () => {
|
|
42
|
+
const result = validate();
|
|
43
|
+
if (!result.valid) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
await onSubmit?.(values);
|
|
47
|
+
}, [onSubmit, validate, values]);
|
|
48
|
+
const reset = React.useCallback(() => {
|
|
49
|
+
setValidationErrors({});
|
|
50
|
+
setValues(initialValuesRef.current);
|
|
51
|
+
}, [setValues]);
|
|
52
|
+
return {
|
|
53
|
+
values,
|
|
54
|
+
errors,
|
|
55
|
+
setValues,
|
|
56
|
+
setFieldValue,
|
|
57
|
+
validate,
|
|
58
|
+
handleSubmit,
|
|
59
|
+
reset,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=useFormController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormController.js","sourceRoot":"","sources":["../../../src/components/form/useFormController.ts"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\n\nimport type {\n FormErrors,\n FormValues,\n UseFormControllerOptions,\n UseFormControllerResult,\n} from './types';\nimport { validateFields } from './validation';\n\nfunction createInitialValues<TName extends string>(\n fields: readonly { name: TName }[],\n initialValues: Partial<FormValues<TName>> | undefined,\n): FormValues<TName> {\n const values = fields.reduce<Record<string, string>>((nextValues, field) => {\n nextValues[field.name] = initialValues?.[field.name] ?? '';\n return nextValues;\n }, {});\n\n return values as FormValues<TName>;\n}\n\nexport function useFormController<TName extends string = string>({\n fields,\n initialValues,\n values: controlledValues,\n errors: externalErrors,\n onChange,\n onSubmit,\n validateOnChange = false,\n}: UseFormControllerOptions<TName>): UseFormControllerResult<TName> {\n const initialValuesRef = React.useRef(createInitialValues(fields, initialValues));\n const [internalValues, setInternalValues] = React.useState<FormValues<TName>>(\n initialValuesRef.current,\n );\n const [validationErrors, setValidationErrors] = React.useState<FormErrors<TName>>({});\n\n const values = controlledValues ?? internalValues;\n const errors = React.useMemo(\n () => ({\n ...validationErrors,\n ...externalErrors,\n }),\n [externalErrors, validationErrors],\n );\n\n const setValues = React.useCallback(\n (nextValues: FormValues<TName>) => {\n if (!controlledValues) {\n setInternalValues(nextValues);\n }\n\n onChange?.(nextValues);\n },\n [controlledValues, onChange],\n );\n\n const validate = React.useCallback(() => {\n const result = validateFields(fields, values);\n setValidationErrors(result.errors);\n return result;\n }, [fields, values]);\n\n const setFieldValue = React.useCallback(\n (name: TName, value: string) => {\n const nextValues = {\n ...values,\n [name]: value,\n };\n\n setValues(nextValues);\n\n if (validateOnChange) {\n const result = validateFields(fields, nextValues);\n setValidationErrors(result.errors);\n }\n },\n [fields, setValues, validateOnChange, values],\n );\n\n const handleSubmit = React.useCallback(async () => {\n const result = validate();\n\n if (!result.valid) {\n return;\n }\n\n await onSubmit?.(values);\n }, [onSubmit, validate, values]);\n\n const reset = React.useCallback(() => {\n setValidationErrors({});\n setValues(initialValuesRef.current);\n }, [setValues]);\n\n return {\n values,\n errors,\n setValues,\n setFieldValue,\n validate,\n handleSubmit,\n reset,\n };\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FormFieldConfig, FormValidationResult, FormValues, ValidationRule } from './types';
|
|
2
|
+
export declare function hasRequiredRule(rules: readonly ValidationRule[] | undefined): boolean;
|
|
3
|
+
export declare function validateValue(value: string, rules: readonly ValidationRule[] | undefined): string | undefined;
|
|
4
|
+
export declare function validateField<TName extends string>(field: FormFieldConfig<TName>, values: FormValues<TName>): string | undefined;
|
|
5
|
+
export declare function validateFields<TName extends string>(fields: readonly FormFieldConfig<TName>[], values: FormValues<TName>): FormValidationResult<TName>;
|
|
6
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/components/form/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAEf,oBAAoB,EACpB,UAAU,EACV,cAAc,EACf,MAAM,SAAS,CAAC;AAIjB,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,GAAG,OAAO,CAErF;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,GAC3C,MAAM,GAAG,SAAS,CAsCpB;AAED,wBAAgB,aAAa,CAAC,KAAK,SAAS,MAAM,EAChD,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,EAC7B,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GACxB,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAS,MAAM,EACjD,MAAM,EAAE,SAAS,eAAe,CAAC,KAAK,CAAC,EAAE,EACzC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GACxB,oBAAoB,CAAC,KAAK,CAAC,CAe7B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2
|
+
export function hasRequiredRule(rules) {
|
|
3
|
+
return rules?.some((rule) => rule.kind === 'required') ?? false;
|
|
4
|
+
}
|
|
5
|
+
export function validateValue(value, rules) {
|
|
6
|
+
if (!rules?.length) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
for (const rule of rules) {
|
|
10
|
+
const normalizedValue = value.trim();
|
|
11
|
+
if (rule.kind === 'required' && normalizedValue.length === 0) {
|
|
12
|
+
return rule.message ?? 'This field is required.';
|
|
13
|
+
}
|
|
14
|
+
if (rule.kind === 'email' &&
|
|
15
|
+
normalizedValue.length > 0 &&
|
|
16
|
+
!emailPattern.test(normalizedValue)) {
|
|
17
|
+
return rule.message ?? 'Enter a valid email address.';
|
|
18
|
+
}
|
|
19
|
+
if (rule.kind === 'minLength' && value.length < rule.value) {
|
|
20
|
+
return rule.message ?? `Enter at least ${rule.value} characters.`;
|
|
21
|
+
}
|
|
22
|
+
if (rule.kind === 'pattern') {
|
|
23
|
+
try {
|
|
24
|
+
const pattern = new RegExp(rule.value);
|
|
25
|
+
if (normalizedValue.length > 0 && !pattern.test(value)) {
|
|
26
|
+
return rule.message ?? 'Enter a valid value.';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return rule.message ?? 'Enter a valid value.';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
export function validateField(field, values) {
|
|
37
|
+
return validateValue(values[field.name], field.rules);
|
|
38
|
+
}
|
|
39
|
+
export function validateFields(fields, values) {
|
|
40
|
+
const errors = {};
|
|
41
|
+
for (const field of fields) {
|
|
42
|
+
const error = validateField(field, values);
|
|
43
|
+
if (error) {
|
|
44
|
+
errors[field.name] = error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
errors,
|
|
49
|
+
valid: Object.keys(errors).length === 0,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/components/form/validation.ts"],"names":[],"mappings":"AAQA,MAAM,YAAY,GAAG,4BAA4B,CAAC;AAElD,MAAM,UAAU,eAAe,CAAC,KAA4C;IAC1E,OAAO,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,KAAK,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAa,EACb,KAA4C;IAE5C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAErC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,IAAI,CAAC,OAAO,IAAI,yBAAyB,CAAC;QACnD,CAAC;QAED,IACE,IAAI,CAAC,IAAI,KAAK,OAAO;YACrB,eAAe,CAAC,MAAM,GAAG,CAAC;YAC1B,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,EACnC,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,IAAI,8BAA8B,CAAC;QACxD,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3D,OAAO,IAAI,CAAC,OAAO,IAAI,kBAAkB,IAAI,CAAC,KAAK,cAAc,CAAC;QACpE,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAEvC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACvD,OAAO,IAAI,CAAC,OAAO,IAAI,sBAAsB,CAAC;gBAChD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC,OAAO,IAAI,sBAAsB,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAA6B,EAC7B,MAAyB;IAEzB,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAyC,EACzC,MAAyB;IAEzB,MAAM,MAAM,GAAgC,EAAE,CAAC;IAE/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAE3C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM;QACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;KACxC,CAAC;AACJ,CAAC","sourcesContent":["import type {\n FormFieldConfig,\n FormValidationErrors,\n FormValidationResult,\n FormValues,\n ValidationRule,\n} from './types';\n\nconst emailPattern = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\nexport function hasRequiredRule(rules: readonly ValidationRule[] | undefined): boolean {\n return rules?.some((rule) => rule.kind === 'required') ?? false;\n}\n\nexport function validateValue(\n value: string,\n rules: readonly ValidationRule[] | undefined,\n): string | undefined {\n if (!rules?.length) {\n return undefined;\n }\n\n for (const rule of rules) {\n const normalizedValue = value.trim();\n\n if (rule.kind === 'required' && normalizedValue.length === 0) {\n return rule.message ?? 'This field is required.';\n }\n\n if (\n rule.kind === 'email' &&\n normalizedValue.length > 0 &&\n !emailPattern.test(normalizedValue)\n ) {\n return rule.message ?? 'Enter a valid email address.';\n }\n\n if (rule.kind === 'minLength' && value.length < rule.value) {\n return rule.message ?? `Enter at least ${rule.value} characters.`;\n }\n\n if (rule.kind === 'pattern') {\n try {\n const pattern = new RegExp(rule.value);\n\n if (normalizedValue.length > 0 && !pattern.test(value)) {\n return rule.message ?? 'Enter a valid value.';\n }\n } catch {\n return rule.message ?? 'Enter a valid value.';\n }\n }\n }\n\n return undefined;\n}\n\nexport function validateField<TName extends string>(\n field: FormFieldConfig<TName>,\n values: FormValues<TName>,\n): string | undefined {\n return validateValue(values[field.name], field.rules);\n}\n\nexport function validateFields<TName extends string>(\n fields: readonly FormFieldConfig<TName>[],\n values: FormValues<TName>,\n): FormValidationResult<TName> {\n const errors: FormValidationErrors<TName> = {};\n\n for (const field of fields) {\n const error = validateField(field, values);\n\n if (error) {\n errors[field.name] = error;\n }\n }\n\n return {\n errors,\n valid: Object.keys(errors).length === 0,\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export type { CheckboxGroupOption, CheckboxGroupProps, CheckboxProps } from './c
|
|
|
8
8
|
export { Checkbox, CheckboxGroup } from './components/checkbox';
|
|
9
9
|
export type { DrawerProps } from './components/drawer';
|
|
10
10
|
export { Drawer } from './components/drawer';
|
|
11
|
+
export type { FormActionsProps, FormErrorProps, FormErrors, FormFieldConfig, FormFieldControlProps, FormFieldInputType, FormFieldProps, FormFieldValue, FormFieldWrapperProps, FormProps, FormValidationErrors, FormValidationResult, FormValues, UseFormControllerOptions, UseFormControllerResult, ValidationRule, } from './components/form';
|
|
12
|
+
export { Form, FormActions, FormError, FormField, hasRequiredRule, useFormController, validateField, validateFields, validateValue, } from './components/form';
|
|
11
13
|
export type { IconProps } from './components/icon';
|
|
12
14
|
export { Icon } from './components/icon';
|
|
13
15
|
export type { IconButtonProps } from './components/icon-button';
|
|
@@ -42,6 +44,8 @@ export type { SidebarLayoutProps } from './layout/sidebar-layout';
|
|
|
42
44
|
export { SidebarLayout } from './layout/sidebar-layout';
|
|
43
45
|
export type { TopbarLayoutProps } from './layout/topbar-layout';
|
|
44
46
|
export { TopbarLayout } from './layout/topbar-layout';
|
|
47
|
+
export type { AuthFormBaseProps, AuthIdentifierKind, ForgotPasswordFormProps, ForgotPasswordFormValues, OtpFormProps, OtpFormValues, SignInFormProps, SignInFormValues, SignUpFormField, SignUpFormProps, SignUpFormValues, } from './patterns/auth';
|
|
48
|
+
export { ForgotPasswordForm, OtpForm, SignInForm, SignUpForm } from './patterns/auth';
|
|
45
49
|
export type { CollectionEditorProps, CollectionEditorRenderItemProps, } from './patterns/collection-editor';
|
|
46
50
|
export { CollectionEditor } from './patterns/collection-editor';
|
|
47
51
|
export type { ConfirmDialogProps } from './patterns/confirm-dialog';
|
|
@@ -50,8 +54,6 @@ export type { DisclosureSectionProps } from './patterns/disclosure-section';
|
|
|
50
54
|
export { DisclosureSection } from './patterns/disclosure-section';
|
|
51
55
|
export type { EmptyStateAction, EmptyStateProps } from './patterns/empty-state';
|
|
52
56
|
export { EmptyState } from './patterns/empty-state';
|
|
53
|
-
export type { FormFieldProps } from './patterns/form-field';
|
|
54
|
-
export { FormField } from './patterns/form-field';
|
|
55
57
|
export type { InspectorFieldProps } from './patterns/inspector-field';
|
|
56
58
|
export { InspectorField } from './patterns/inspector-field';
|
|
57
59
|
export type { NoticeProps } from './patterns/notice';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EACV,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|