@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/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { Button } from './components/button';
|
|
|
3
3
|
export { Card } from './components/card';
|
|
4
4
|
export { Checkbox, CheckboxGroup } from './components/checkbox';
|
|
5
5
|
export { Drawer } from './components/drawer';
|
|
6
|
+
export { Form, FormActions, FormError, FormField, hasRequiredRule, useFormController, validateField, validateFields, validateValue, } from './components/form';
|
|
6
7
|
export { Icon } from './components/icon';
|
|
7
8
|
export { IconButton } from './components/icon-button';
|
|
8
9
|
export { Input } from './components/input';
|
|
@@ -20,11 +21,11 @@ export { PageSection } from './layout/page-section';
|
|
|
20
21
|
export { SettingsLayout } from './layout/settings-layout';
|
|
21
22
|
export { SidebarLayout } from './layout/sidebar-layout';
|
|
22
23
|
export { TopbarLayout } from './layout/topbar-layout';
|
|
24
|
+
export { ForgotPasswordForm, OtpForm, SignInForm, SignUpForm } from './patterns/auth';
|
|
23
25
|
export { CollectionEditor } from './patterns/collection-editor';
|
|
24
26
|
export { ConfirmDialog } from './patterns/confirm-dialog';
|
|
25
27
|
export { DisclosureSection } from './patterns/disclosure-section';
|
|
26
28
|
export { EmptyState } from './patterns/empty-state';
|
|
27
|
-
export { FormField } from './patterns/form-field';
|
|
28
29
|
export { InspectorField } from './patterns/inspector-field';
|
|
29
30
|
export { Notice } from './patterns/notice';
|
|
30
31
|
export { Panel } from './patterns/panel';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmB7C,OAAO,EACL,IAAI,EACJ,WAAW,EACX,SAAS,EACT,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AActD,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,cAAc,SAAS,CAAC","sourcesContent":["export type { BadgeProps } from './components/badge';\nexport { Badge } from './components/badge';\nexport type { ButtonProps } from './components/button';\nexport { Button } from './components/button';\nexport type { CardProps } from './components/card';\nexport { Card } from './components/card';\nexport type { CheckboxGroupOption, CheckboxGroupProps, CheckboxProps } from './components/checkbox';\nexport { Checkbox, CheckboxGroup } from './components/checkbox';\nexport type { DrawerProps } from './components/drawer';\nexport { Drawer } from './components/drawer';\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 './components/form';\nexport {\n Form,\n FormActions,\n FormError,\n FormField,\n hasRequiredRule,\n useFormController,\n validateField,\n validateFields,\n validateValue,\n} from './components/form';\nexport type { IconProps } from './components/icon';\nexport { Icon } from './components/icon';\nexport type { IconButtonProps } from './components/icon-button';\nexport { IconButton } from './components/icon-button';\nexport type { InputProps } from './components/input';\nexport { Input } from './components/input';\nexport type { ModalProps } from './components/modal';\nexport { Modal } from './components/modal';\nexport type { RadioGroupOption, RadioGroupProps, RadioProps } from './components/radio';\nexport { Radio, RadioGroup } from './components/radio';\nexport type { SelectOption, SelectProps } from './components/select';\nexport { Select } from './components/select';\nexport type { TabItem, TabsProps } from './components/tabs';\nexport { Tabs } from './components/tabs';\nexport type { TextareaProps } from './components/textarea';\nexport { Textarea } from './components/textarea';\nexport type { ToolbarActionProps, ToolbarProps } from './components/toolbar';\nexport { Toolbar, ToolbarAction } from './components/toolbar';\nexport type { AppShellProps } from './layout/app-shell';\nexport { AppShell } from './layout/app-shell';\nexport type { AuthLayoutProps } from './layout/auth-layout';\nexport { AuthLayout } from './layout/auth-layout';\nexport type { PageProps } from './layout/page';\nexport { Page } from './layout/page';\nexport type { PageHeaderProps } from './layout/page-header';\nexport { PageHeader } from './layout/page-header';\nexport type { PageSectionProps } from './layout/page-section';\nexport { PageSection } from './layout/page-section';\nexport type { SettingsLayoutProps } from './layout/settings-layout';\nexport { SettingsLayout } from './layout/settings-layout';\nexport type { SidebarLayoutProps } from './layout/sidebar-layout';\nexport { SidebarLayout } from './layout/sidebar-layout';\nexport type { TopbarLayoutProps } from './layout/topbar-layout';\nexport { TopbarLayout } from './layout/topbar-layout';\nexport type {\n AuthFormBaseProps,\n AuthIdentifierKind,\n ForgotPasswordFormProps,\n ForgotPasswordFormValues,\n OtpFormProps,\n OtpFormValues,\n SignInFormProps,\n SignInFormValues,\n SignUpFormField,\n SignUpFormProps,\n SignUpFormValues,\n} from './patterns/auth';\nexport { ForgotPasswordForm, OtpForm, SignInForm, SignUpForm } from './patterns/auth';\nexport type {\n CollectionEditorProps,\n CollectionEditorRenderItemProps,\n} from './patterns/collection-editor';\nexport { CollectionEditor } from './patterns/collection-editor';\nexport type { ConfirmDialogProps } from './patterns/confirm-dialog';\nexport { ConfirmDialog } from './patterns/confirm-dialog';\nexport type { DisclosureSectionProps } from './patterns/disclosure-section';\nexport { DisclosureSection } from './patterns/disclosure-section';\nexport type { EmptyStateAction, EmptyStateProps } from './patterns/empty-state';\nexport { EmptyState } from './patterns/empty-state';\nexport type { InspectorFieldProps } from './patterns/inspector-field';\nexport { InspectorField } from './patterns/inspector-field';\nexport type { NoticeProps } from './patterns/notice';\nexport { Notice } from './patterns/notice';\nexport type { PanelProps } from './patterns/panel';\nexport { Panel } from './patterns/panel';\nexport type { ResponsivePanelProps } from './patterns/responsive-panel';\nexport { ResponsivePanel } from './patterns/responsive-panel';\nexport type { SectionHeaderProps } from './patterns/section-header';\nexport { SectionHeader } from './patterns/section-header';\nexport type { SettingsRowProps } from './patterns/settings-row';\nexport { SettingsRow } from './patterns/settings-row';\nexport type { SwitchFieldProps } from './patterns/switch-field';\nexport { SwitchField } from './patterns/switch-field';\nexport type { PaletteItemProps, TileGridProps } from './patterns/tile-grid';\nexport { PaletteItem, TileGrid } from './patterns/tile-grid';\nexport type { TreeItemNode, TreeItemRenderProps, TreeViewProps } from './patterns/tree-view';\nexport { TreeItem, TreeView } from './patterns/tree-view';\nexport * from './theme';\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ForgotPasswordFormProps } from './types';
|
|
3
|
+
export declare function ForgotPasswordForm({ identifiers, identifierLabel, signInLabel, loading, disabled, error, submitLabel, onSubmit, onSignIn, testID, }: ForgotPasswordFormProps): React.JSX.Element;
|
|
4
|
+
//# sourceMappingURL=ForgotPasswordForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForgotPasswordForm.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/ForgotPasswordForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAWvD,wBAAgB,kBAAkB,CAAC,EACjC,WAAgC,EAChC,eAAe,EACf,WAAuB,EACvB,OAAe,EACf,QAAgB,EAChB,KAAK,EACL,WAAyB,EACzB,QAAQ,EACR,QAAQ,EACR,MAAM,GACP,EAAE,uBAAuB,qBAwDzB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Button } from '../../components/button';
|
|
4
|
+
import { Form } from '../../components/form';
|
|
5
|
+
import { defaultIdentifiers, normalizeIdentifierKind, resolveIdentifierLabel, resolveIdentifierRules, resolveIdentifierType, } from './utils';
|
|
6
|
+
export function ForgotPasswordForm({ identifiers = defaultIdentifiers, identifierLabel, signInLabel = 'Sign in', loading = false, disabled = false, error, submitLabel = 'Send code', onSubmit, onSignIn, testID, }) {
|
|
7
|
+
const [values, setValues] = React.useState({
|
|
8
|
+
identifier: '',
|
|
9
|
+
});
|
|
10
|
+
const fields = React.useMemo(() => [
|
|
11
|
+
{
|
|
12
|
+
name: 'identifier',
|
|
13
|
+
label: identifierLabel ?? resolveIdentifierLabel(identifiers),
|
|
14
|
+
type: resolveIdentifierType(identifiers),
|
|
15
|
+
autoCapitalize: 'none',
|
|
16
|
+
rules: resolveIdentifierRules(identifiers),
|
|
17
|
+
},
|
|
18
|
+
], [identifierLabel, identifiers]);
|
|
19
|
+
const handleSubmit = React.useCallback((formValues) => onSubmit({
|
|
20
|
+
identifier: formValues.identifier.trim(),
|
|
21
|
+
identifierKind: normalizeIdentifierKind(formValues.identifier, identifiers),
|
|
22
|
+
}), [identifiers, onSubmit]);
|
|
23
|
+
return (<Form actions={onSignIn ? (<Stack direction="row" gap="s" wrap="wrap">
|
|
24
|
+
<Button disabled={disabled || loading} emphasis="ghost" onPress={() => {
|
|
25
|
+
void onSignIn();
|
|
26
|
+
}} size="s" tone="neutral">
|
|
27
|
+
{signInLabel}
|
|
28
|
+
</Button>
|
|
29
|
+
</Stack>) : undefined} disabled={disabled} error={error} fields={fields} loading={loading} onChange={setValues} onSubmit={handleSubmit} submitLabel={submitLabel} testID={testID} values={values}/>);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ForgotPasswordForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForgotPasswordForm.js","sourceRoot":"","sources":["../../../src/patterns/auth/ForgotPasswordForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAyC,MAAM,uBAAuB,CAAC;AAEpF,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAIjB,MAAM,UAAU,kBAAkB,CAAC,EACjC,WAAW,GAAG,kBAAkB,EAChC,eAAe,EACf,WAAW,GAAG,SAAS,EACvB,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,WAAW,GAAG,WAAW,EACzB,QAAQ,EACR,QAAQ,EACR,MAAM,GACkB;IACxB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAsC;QAC9E,UAAU,EAAE,EAAE;KACf,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC;QACJ;YACE,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,eAAe,IAAI,sBAAsB,CAAC,WAAW,CAAC;YAC7D,IAAI,EAAE,qBAAqB,CAAC,WAAW,CAAC;YACxC,cAAc,EAAE,MAAM;YACtB,KAAK,EAAE,sBAAsB,CAAC,WAAW,CAAC;SAC3C;KACF,EACD,CAAC,eAAe,EAAE,WAAW,CAAC,CAC/B,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CACpC,CAAC,UAA+C,EAAE,EAAE,CAClD,QAAQ,CAAC;QACP,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE;QACxC,cAAc,EAAE,uBAAuB,CAAC,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC;KAC5E,CAAC,EACJ,CAAC,WAAW,EAAE,QAAQ,CAAC,CACxB,CAAC;IAEF,OAAO,CACL,CAAC,IAAI,CACH,OAAO,CAAC,CACN,QAAQ,CAAC,CAAC,CAAC,CACT,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CACxC;YAAA,CAAC,MAAM,CACL,QAAQ,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAC9B,QAAQ,CAAC,OAAO,CAChB,OAAO,CAAC,CAAC,GAAG,EAAE;gBACZ,KAAK,QAAQ,EAAE,CAAC;YAClB,CAAC,CAAC,CACF,IAAI,CAAC,GAAG,CACR,IAAI,CAAC,SAAS,CAEd;cAAA,CAAC,WAAW,CACd;YAAA,EAAE,MAAM,CACV;UAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,SACN,CAAC,CACD,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,SAAS,CAAC,CACpB,QAAQ,CAAC,CAAC,YAAY,CAAC,CACvB,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,MAAM,CAAC,CAAC,MAAM,CAAC,EACf,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { Stack } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Button } from '../../components/button';\nimport { Form, type FormFieldConfig, type FormValues } from '../../components/form';\nimport type { ForgotPasswordFormProps } from './types';\nimport {\n defaultIdentifiers,\n normalizeIdentifierKind,\n resolveIdentifierLabel,\n resolveIdentifierRules,\n resolveIdentifierType,\n} from './utils';\n\ntype ForgotPasswordFieldName = 'identifier';\n\nexport function ForgotPasswordForm({\n identifiers = defaultIdentifiers,\n identifierLabel,\n signInLabel = 'Sign in',\n loading = false,\n disabled = false,\n error,\n submitLabel = 'Send code',\n onSubmit,\n onSignIn,\n testID,\n}: ForgotPasswordFormProps) {\n const [values, setValues] = React.useState<FormValues<ForgotPasswordFieldName>>({\n identifier: '',\n });\n const fields = React.useMemo<readonly FormFieldConfig<ForgotPasswordFieldName>[]>(\n () => [\n {\n name: 'identifier',\n label: identifierLabel ?? resolveIdentifierLabel(identifiers),\n type: resolveIdentifierType(identifiers),\n autoCapitalize: 'none',\n rules: resolveIdentifierRules(identifiers),\n },\n ],\n [identifierLabel, identifiers],\n );\n\n const handleSubmit = React.useCallback(\n (formValues: FormValues<ForgotPasswordFieldName>) =>\n onSubmit({\n identifier: formValues.identifier.trim(),\n identifierKind: normalizeIdentifierKind(formValues.identifier, identifiers),\n }),\n [identifiers, onSubmit],\n );\n\n return (\n <Form\n actions={\n onSignIn ? (\n <Stack direction=\"row\" gap=\"s\" wrap=\"wrap\">\n <Button\n disabled={disabled || loading}\n emphasis=\"ghost\"\n onPress={() => {\n void onSignIn();\n }}\n size=\"s\"\n tone=\"neutral\"\n >\n {signInLabel}\n </Button>\n </Stack>\n ) : undefined\n }\n disabled={disabled}\n error={error}\n fields={fields}\n loading={loading}\n onChange={setValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel}\n testID={testID}\n values={values}\n />\n );\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { OtpFormProps } from './types';
|
|
3
|
+
export declare function OtpForm({ length, otpLabel, resendLabel, resendDisabled, resendLoading, loading, disabled, error, submitLabel, onSubmit, onResend, testID, }: OtpFormProps): React.JSX.Element;
|
|
4
|
+
//# sourceMappingURL=OtpForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OtpForm.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/OtpForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,wBAAgB,OAAO,CAAC,EACtB,MAAU,EACV,QAAiB,EACjB,WAA2B,EAC3B,cAAsB,EACtB,aAAqB,EACrB,OAAe,EACf,QAAgB,EAChB,KAAK,EACL,WAA2B,EAC3B,QAAQ,EACR,QAAQ,EACR,MAAM,GACP,EAAE,YAAY,qBAyDd"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Button } from '../../components/button';
|
|
4
|
+
import { Form } from '../../components/form';
|
|
5
|
+
export function OtpForm({ length = 6, otpLabel = 'Code', resendLabel = 'Resend code', resendDisabled = false, resendLoading = false, loading = false, disabled = false, error, submitLabel = 'Verify code', onSubmit, onResend, testID, }) {
|
|
6
|
+
const resolvedLength = Math.max(1, length);
|
|
7
|
+
const [values, setValues] = React.useState({
|
|
8
|
+
otp: '',
|
|
9
|
+
});
|
|
10
|
+
const fields = React.useMemo(() => [
|
|
11
|
+
{
|
|
12
|
+
name: 'otp',
|
|
13
|
+
label: otpLabel,
|
|
14
|
+
type: 'otp',
|
|
15
|
+
maxLength: resolvedLength,
|
|
16
|
+
rules: [{ kind: 'required' }, { kind: 'minLength', value: resolvedLength }],
|
|
17
|
+
},
|
|
18
|
+
], [otpLabel, resolvedLength]);
|
|
19
|
+
const handleSubmit = React.useCallback((formValues) => onSubmit({
|
|
20
|
+
otp: formValues.otp.trim(),
|
|
21
|
+
}), [onSubmit]);
|
|
22
|
+
return (<Form actions={onResend ? (<Stack direction="row" gap="s" wrap="wrap">
|
|
23
|
+
<Button disabled={disabled || loading || resendDisabled} emphasis="ghost" loading={resendLoading} onPress={() => {
|
|
24
|
+
void onResend();
|
|
25
|
+
}} size="s" tone="neutral">
|
|
26
|
+
{resendLabel}
|
|
27
|
+
</Button>
|
|
28
|
+
</Stack>) : undefined} disabled={disabled} error={error} fields={fields} loading={loading} onChange={setValues} onSubmit={handleSubmit} submitLabel={submitLabel} testID={testID} values={values}/>);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=OtpForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OtpForm.js","sourceRoot":"","sources":["../../../src/patterns/auth/OtpForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAyC,MAAM,uBAAuB,CAAC;AAKpF,MAAM,UAAU,OAAO,CAAC,EACtB,MAAM,GAAG,CAAC,EACV,QAAQ,GAAG,MAAM,EACjB,WAAW,GAAG,aAAa,EAC3B,cAAc,GAAG,KAAK,EACtB,aAAa,GAAG,KAAK,EACrB,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,WAAW,GAAG,aAAa,EAC3B,QAAQ,EACR,QAAQ,EACR,MAAM,GACO;IACb,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAA2B;QACnE,GAAG,EAAE,EAAE;KACR,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC;QACJ;YACE,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,cAAc;YACzB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;SAC5E;KACF,EACD,CAAC,QAAQ,EAAE,cAAc,CAAC,CAC3B,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CACpC,CAAC,UAAoC,EAAE,EAAE,CACvC,QAAQ,CAAC;QACP,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE;KAC3B,CAAC,EACJ,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,OAAO,CACL,CAAC,IAAI,CACH,OAAO,CAAC,CACN,QAAQ,CAAC,CAAC,CAAC,CACT,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CACxC;YAAA,CAAC,MAAM,CACL,QAAQ,CAAC,CAAC,QAAQ,IAAI,OAAO,IAAI,cAAc,CAAC,CAChD,QAAQ,CAAC,OAAO,CAChB,OAAO,CAAC,CAAC,aAAa,CAAC,CACvB,OAAO,CAAC,CAAC,GAAG,EAAE;gBACZ,KAAK,QAAQ,EAAE,CAAC;YAClB,CAAC,CAAC,CACF,IAAI,CAAC,GAAG,CACR,IAAI,CAAC,SAAS,CAEd;cAAA,CAAC,WAAW,CACd;YAAA,EAAE,MAAM,CACV;UAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,SACN,CAAC,CACD,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,SAAS,CAAC,CACpB,QAAQ,CAAC,CAAC,YAAY,CAAC,CACvB,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,MAAM,CAAC,CAAC,MAAM,CAAC,EACf,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { Stack } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Button } from '../../components/button';\nimport { Form, type FormFieldConfig, type FormValues } from '../../components/form';\nimport type { OtpFormProps } from './types';\n\ntype OtpFieldName = 'otp';\n\nexport function OtpForm({\n length = 6,\n otpLabel = 'Code',\n resendLabel = 'Resend code',\n resendDisabled = false,\n resendLoading = false,\n loading = false,\n disabled = false,\n error,\n submitLabel = 'Verify code',\n onSubmit,\n onResend,\n testID,\n}: OtpFormProps) {\n const resolvedLength = Math.max(1, length);\n const [values, setValues] = React.useState<FormValues<OtpFieldName>>({\n otp: '',\n });\n const fields = React.useMemo<readonly FormFieldConfig<OtpFieldName>[]>(\n () => [\n {\n name: 'otp',\n label: otpLabel,\n type: 'otp',\n maxLength: resolvedLength,\n rules: [{ kind: 'required' }, { kind: 'minLength', value: resolvedLength }],\n },\n ],\n [otpLabel, resolvedLength],\n );\n\n const handleSubmit = React.useCallback(\n (formValues: FormValues<OtpFieldName>) =>\n onSubmit({\n otp: formValues.otp.trim(),\n }),\n [onSubmit],\n );\n\n return (\n <Form\n actions={\n onResend ? (\n <Stack direction=\"row\" gap=\"s\" wrap=\"wrap\">\n <Button\n disabled={disabled || loading || resendDisabled}\n emphasis=\"ghost\"\n loading={resendLoading}\n onPress={() => {\n void onResend();\n }}\n size=\"s\"\n tone=\"neutral\"\n >\n {resendLabel}\n </Button>\n </Stack>\n ) : undefined\n }\n disabled={disabled}\n error={error}\n fields={fields}\n loading={loading}\n onChange={setValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel}\n testID={testID}\n values={values}\n />\n );\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SignInFormProps } from './types';
|
|
3
|
+
export declare function SignInForm({ identifiers, identifierLabel, secretLabel, forgotPasswordLabel, signUpLabel, loading, disabled, error, submitLabel, onSubmit, onForgotPassword, onSignUp, testID, }: SignInFormProps): React.JSX.Element;
|
|
4
|
+
//# sourceMappingURL=SignInForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignInForm.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/SignInForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAW/C,wBAAgB,UAAU,CAAC,EACzB,WAAgC,EAChC,eAAe,EACf,WAAwB,EACxB,mBAAuC,EACvC,WAAuB,EACvB,OAAe,EACf,QAAgB,EAChB,KAAK,EACL,WAAuB,EACvB,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,MAAM,GACP,EAAE,eAAe,qBAgFjB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Button } from '../../components/button';
|
|
4
|
+
import { Form } from '../../components/form';
|
|
5
|
+
import { defaultIdentifiers, normalizeIdentifierKind, resolveIdentifierLabel, resolveIdentifierRules, resolveIdentifierType, } from './utils';
|
|
6
|
+
export function SignInForm({ identifiers = defaultIdentifiers, identifierLabel, secretLabel = 'Password', forgotPasswordLabel = 'Forgot password', signUpLabel = 'Sign up', loading = false, disabled = false, error, submitLabel = 'Sign in', onSubmit, onForgotPassword, onSignUp, testID, }) {
|
|
7
|
+
const [values, setValues] = React.useState({
|
|
8
|
+
identifier: '',
|
|
9
|
+
secret: '',
|
|
10
|
+
});
|
|
11
|
+
const hasActions = Boolean(onForgotPassword ?? onSignUp);
|
|
12
|
+
const fields = React.useMemo(() => [
|
|
13
|
+
{
|
|
14
|
+
name: 'identifier',
|
|
15
|
+
label: identifierLabel ?? resolveIdentifierLabel(identifiers),
|
|
16
|
+
type: resolveIdentifierType(identifiers),
|
|
17
|
+
autoCapitalize: 'none',
|
|
18
|
+
rules: resolveIdentifierRules(identifiers),
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'secret',
|
|
22
|
+
label: secretLabel,
|
|
23
|
+
type: 'password',
|
|
24
|
+
rules: [{ kind: 'required' }],
|
|
25
|
+
},
|
|
26
|
+
], [identifierLabel, identifiers, secretLabel]);
|
|
27
|
+
const handleSubmit = React.useCallback((formValues) => onSubmit({
|
|
28
|
+
identifier: formValues.identifier.trim(),
|
|
29
|
+
identifierKind: normalizeIdentifierKind(formValues.identifier, identifiers),
|
|
30
|
+
secret: formValues.secret,
|
|
31
|
+
}), [identifiers, onSubmit]);
|
|
32
|
+
return (<Form actions={hasActions ? (<Stack direction="row" gap="s" wrap="wrap">
|
|
33
|
+
{onForgotPassword ? (<Button disabled={disabled || loading} emphasis="ghost" onPress={() => {
|
|
34
|
+
void onForgotPassword();
|
|
35
|
+
}} size="s" tone="neutral">
|
|
36
|
+
{forgotPasswordLabel}
|
|
37
|
+
</Button>) : null}
|
|
38
|
+
{onSignUp ? (<Button disabled={disabled || loading} emphasis="ghost" onPress={() => {
|
|
39
|
+
void onSignUp();
|
|
40
|
+
}} size="s" tone="neutral">
|
|
41
|
+
{signUpLabel}
|
|
42
|
+
</Button>) : null}
|
|
43
|
+
</Stack>) : undefined} disabled={disabled} error={error} fields={fields} loading={loading} onChange={setValues} onSubmit={handleSubmit} submitLabel={submitLabel} testID={testID} values={values}/>);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=SignInForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignInForm.js","sourceRoot":"","sources":["../../../src/patterns/auth/SignInForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Stack } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Button } from '../../components/button';\nimport { Form, type FormFieldConfig, type FormValues } from '../../components/form';\nimport type { SignInFormProps } from './types';\nimport {\n defaultIdentifiers,\n normalizeIdentifierKind,\n resolveIdentifierLabel,\n resolveIdentifierRules,\n resolveIdentifierType,\n} from './utils';\n\ntype SignInFieldName = 'identifier' | 'secret';\n\nexport function SignInForm({\n identifiers = defaultIdentifiers,\n identifierLabel,\n secretLabel = 'Password',\n forgotPasswordLabel = 'Forgot password',\n signUpLabel = 'Sign up',\n loading = false,\n disabled = false,\n error,\n submitLabel = 'Sign in',\n onSubmit,\n onForgotPassword,\n onSignUp,\n testID,\n}: SignInFormProps) {\n const [values, setValues] = React.useState<FormValues<SignInFieldName>>({\n identifier: '',\n secret: '',\n });\n const hasActions = Boolean(onForgotPassword ?? onSignUp);\n const fields = React.useMemo<readonly FormFieldConfig<SignInFieldName>[]>(\n () => [\n {\n name: 'identifier',\n label: identifierLabel ?? resolveIdentifierLabel(identifiers),\n type: resolveIdentifierType(identifiers),\n autoCapitalize: 'none',\n rules: resolveIdentifierRules(identifiers),\n },\n {\n name: 'secret',\n label: secretLabel,\n type: 'password',\n rules: [{ kind: 'required' }],\n },\n ],\n [identifierLabel, identifiers, secretLabel],\n );\n\n const handleSubmit = React.useCallback(\n (formValues: FormValues<SignInFieldName>) =>\n onSubmit({\n identifier: formValues.identifier.trim(),\n identifierKind: normalizeIdentifierKind(formValues.identifier, identifiers),\n secret: formValues.secret,\n }),\n [identifiers, onSubmit],\n );\n\n return (\n <Form\n actions={\n hasActions ? (\n <Stack direction=\"row\" gap=\"s\" wrap=\"wrap\">\n {onForgotPassword ? (\n <Button\n disabled={disabled || loading}\n emphasis=\"ghost\"\n onPress={() => {\n void onForgotPassword();\n }}\n size=\"s\"\n tone=\"neutral\"\n >\n {forgotPasswordLabel}\n </Button>\n ) : null}\n {onSignUp ? (\n <Button\n disabled={disabled || loading}\n emphasis=\"ghost\"\n onPress={() => {\n void onSignUp();\n }}\n size=\"s\"\n tone=\"neutral\"\n >\n {signUpLabel}\n </Button>\n ) : null}\n </Stack>\n ) : undefined\n }\n disabled={disabled}\n error={error}\n fields={fields}\n loading={loading}\n onChange={setValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel}\n testID={testID}\n values={values}\n />\n );\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SignUpFormProps } from './types';
|
|
3
|
+
export declare function SignUpForm({ fields, signInLabel, loading, disabled, error, submitLabel, onSubmit, onSignIn, testID, }: SignUpFormProps): React.JSX.Element;
|
|
4
|
+
//# sourceMappingURL=SignUpForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignUpForm.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/SignUpForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA2B/C,wBAAgB,UAAU,CAAC,EACzB,MAA4B,EAC5B,WAAuB,EACvB,OAAe,EACf,QAAgB,EAChB,KAAK,EACL,WAAuB,EACvB,QAAQ,EACR,QAAQ,EACR,MAAM,GACP,EAAE,eAAe,qBAiCjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Button } from '../../components/button';
|
|
4
|
+
import { Form } from '../../components/form';
|
|
5
|
+
const defaultSignUpFields = [
|
|
6
|
+
{
|
|
7
|
+
name: 'email',
|
|
8
|
+
label: 'Email',
|
|
9
|
+
type: 'email',
|
|
10
|
+
autoCapitalize: 'none',
|
|
11
|
+
rules: [{ kind: 'required' }, { kind: 'email' }],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'password',
|
|
15
|
+
label: 'Password',
|
|
16
|
+
type: 'password',
|
|
17
|
+
rules: [{ kind: 'required' }, { kind: 'minLength', value: 8 }],
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
function createValues(fields) {
|
|
21
|
+
const values = fields.reduce((nextValues, field) => {
|
|
22
|
+
nextValues[field.name] = '';
|
|
23
|
+
return nextValues;
|
|
24
|
+
}, {});
|
|
25
|
+
return values;
|
|
26
|
+
}
|
|
27
|
+
export function SignUpForm({ fields = defaultSignUpFields, signInLabel = 'Sign in', loading = false, disabled = false, error, submitLabel = 'Sign up', onSubmit, onSignIn, testID, }) {
|
|
28
|
+
const [values, setValues] = React.useState(() => createValues(fields));
|
|
29
|
+
return (<Form actions={onSignIn ? (<Stack direction="row" gap="s" wrap="wrap">
|
|
30
|
+
<Button disabled={disabled || loading} emphasis="ghost" onPress={() => {
|
|
31
|
+
void onSignIn();
|
|
32
|
+
}} size="s" tone="neutral">
|
|
33
|
+
{signInLabel}
|
|
34
|
+
</Button>
|
|
35
|
+
</Stack>) : undefined} disabled={disabled} error={error} fields={fields} loading={loading} onChange={setValues} onSubmit={onSubmit} submitLabel={submitLabel} testID={testID} values={values}/>);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=SignUpForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignUpForm.js","sourceRoot":"","sources":["../../../src/patterns/auth/SignUpForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAyC,MAAM,uBAAuB,CAAC;AAGpF,MAAM,mBAAmB,GAAG;IAC1B;QACE,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,OAAO;QACb,cAAc,EAAE,MAAM;QACtB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;KACjD;IACD;QACE,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;KAC/D;CAC4C,CAAC;AAEhD,SAAS,YAAY,CAAC,MAAkC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAyB,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;QACzE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,OAAO,UAAU,CAAC;IACpB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,MAAM,GAAG,mBAAmB,EAC5B,WAAW,GAAG,SAAS,EACvB,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,WAAW,GAAG,SAAS,EACvB,QAAQ,EACR,QAAQ,EACR,MAAM,GACU;IAChB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAa,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAEnF,OAAO,CACL,CAAC,IAAI,CACH,OAAO,CAAC,CACN,QAAQ,CAAC,CAAC,CAAC,CACT,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CACxC;YAAA,CAAC,MAAM,CACL,QAAQ,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAC9B,QAAQ,CAAC,OAAO,CAChB,OAAO,CAAC,CAAC,GAAG,EAAE;gBACZ,KAAK,QAAQ,EAAE,CAAC;YAClB,CAAC,CAAC,CACF,IAAI,CAAC,GAAG,CACR,IAAI,CAAC,SAAS,CAEd;cAAA,CAAC,WAAW,CACd;YAAA,EAAE,MAAM,CACV;UAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,SACN,CAAC,CACD,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,QAAQ,CAAC,CAAC,SAAS,CAAC,CACpB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,MAAM,CAAC,CAAC,MAAM,CAAC,EACf,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { Stack } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Button } from '../../components/button';\nimport { Form, type FormFieldConfig, type FormValues } from '../../components/form';\nimport type { SignUpFormProps } from './types';\n\nconst defaultSignUpFields = [\n {\n name: 'email',\n label: 'Email',\n type: 'email',\n autoCapitalize: 'none',\n rules: [{ kind: 'required' }, { kind: 'email' }],\n },\n {\n name: 'password',\n label: 'Password',\n type: 'password',\n rules: [{ kind: 'required' }, { kind: 'minLength', value: 8 }],\n },\n] as const satisfies readonly FormFieldConfig[];\n\nfunction createValues(fields: readonly FormFieldConfig[]): FormValues {\n const values = fields.reduce<Record<string, string>>((nextValues, field) => {\n nextValues[field.name] = '';\n return nextValues;\n }, {});\n\n return values;\n}\n\nexport function SignUpForm({\n fields = defaultSignUpFields,\n signInLabel = 'Sign in',\n loading = false,\n disabled = false,\n error,\n submitLabel = 'Sign up',\n onSubmit,\n onSignIn,\n testID,\n}: SignUpFormProps) {\n const [values, setValues] = React.useState<FormValues>(() => createValues(fields));\n\n return (\n <Form\n actions={\n onSignIn ? (\n <Stack direction=\"row\" gap=\"s\" wrap=\"wrap\">\n <Button\n disabled={disabled || loading}\n emphasis=\"ghost\"\n onPress={() => {\n void onSignIn();\n }}\n size=\"s\"\n tone=\"neutral\"\n >\n {signInLabel}\n </Button>\n </Stack>\n ) : undefined\n }\n disabled={disabled}\n error={error}\n fields={fields}\n loading={loading}\n onChange={setValues}\n onSubmit={onSubmit}\n submitLabel={submitLabel}\n testID={testID}\n values={values}\n />\n );\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ForgotPasswordForm } from './ForgotPasswordForm';
|
|
2
|
+
export { OtpForm } from './OtpForm';
|
|
3
|
+
export { SignInForm } from './SignInForm';
|
|
4
|
+
export { SignUpForm } from './SignUpForm';
|
|
5
|
+
export type { AuthFormBaseProps, AuthIdentifierKind, ForgotPasswordFormProps, ForgotPasswordFormValues, OtpFormProps, OtpFormValues, SignInFormProps, SignInFormValues, SignUpFormField, SignUpFormProps, SignUpFormValues, } from './types';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/patterns/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { ForgotPasswordForm } from './ForgotPasswordForm';\nexport { OtpForm } from './OtpForm';\nexport { SignInForm } from './SignInForm';\nexport { SignUpForm } from './SignUpForm';\nexport type {\n AuthFormBaseProps,\n AuthIdentifierKind,\n ForgotPasswordFormProps,\n ForgotPasswordFormValues,\n OtpFormProps,\n OtpFormValues,\n SignInFormProps,\n SignInFormValues,\n SignUpFormField,\n SignUpFormProps,\n SignUpFormValues,\n} from './types';\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { FormFieldConfig, FormValues } from '../../components/form';
|
|
3
|
+
export type AuthIdentifierKind = 'email' | 'phone' | 'username';
|
|
4
|
+
export interface AuthFormBaseProps {
|
|
5
|
+
loading?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
error?: React.ReactNode;
|
|
8
|
+
submitLabel?: React.ReactNode;
|
|
9
|
+
testID?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SignInFormValues {
|
|
12
|
+
identifier: string;
|
|
13
|
+
identifierKind: AuthIdentifierKind;
|
|
14
|
+
secret: string;
|
|
15
|
+
}
|
|
16
|
+
export interface SignInFormProps extends AuthFormBaseProps {
|
|
17
|
+
identifiers?: readonly AuthIdentifierKind[];
|
|
18
|
+
identifierLabel?: React.ReactNode;
|
|
19
|
+
secretLabel?: React.ReactNode;
|
|
20
|
+
forgotPasswordLabel?: React.ReactNode;
|
|
21
|
+
signUpLabel?: React.ReactNode;
|
|
22
|
+
onSubmit: (values: SignInFormValues) => void | Promise<void>;
|
|
23
|
+
onForgotPassword?: () => void | Promise<void>;
|
|
24
|
+
onSignUp?: () => void | Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export type SignUpFormValues = FormValues;
|
|
27
|
+
export type SignUpFormField = FormFieldConfig;
|
|
28
|
+
export interface SignUpFormProps extends AuthFormBaseProps {
|
|
29
|
+
fields?: readonly SignUpFormField[];
|
|
30
|
+
signInLabel?: React.ReactNode;
|
|
31
|
+
onSubmit: (values: SignUpFormValues) => void | Promise<void>;
|
|
32
|
+
onSignIn?: () => void | Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface ForgotPasswordFormValues {
|
|
35
|
+
identifier: string;
|
|
36
|
+
identifierKind: AuthIdentifierKind;
|
|
37
|
+
}
|
|
38
|
+
export interface ForgotPasswordFormProps extends AuthFormBaseProps {
|
|
39
|
+
identifiers?: readonly AuthIdentifierKind[];
|
|
40
|
+
identifierLabel?: React.ReactNode;
|
|
41
|
+
signInLabel?: React.ReactNode;
|
|
42
|
+
onSubmit: (values: ForgotPasswordFormValues) => void | Promise<void>;
|
|
43
|
+
onSignIn?: () => void | Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
export interface OtpFormValues {
|
|
46
|
+
otp: string;
|
|
47
|
+
}
|
|
48
|
+
export interface OtpFormProps extends AuthFormBaseProps {
|
|
49
|
+
length?: number;
|
|
50
|
+
otpLabel?: React.ReactNode;
|
|
51
|
+
resendLabel?: React.ReactNode;
|
|
52
|
+
resendDisabled?: boolean;
|
|
53
|
+
resendLoading?: boolean;
|
|
54
|
+
onSubmit: (values: OtpFormValues) => void | Promise<void>;
|
|
55
|
+
onResend?: () => void | Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/patterns/auth/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nimport type { FormFieldConfig, FormValues } from '../../components/form';\n\nexport type AuthIdentifierKind = 'email' | 'phone' | 'username';\n\nexport interface AuthFormBaseProps {\n loading?: boolean;\n disabled?: boolean;\n error?: React.ReactNode;\n submitLabel?: React.ReactNode;\n testID?: string;\n}\n\nexport interface SignInFormValues {\n identifier: string;\n identifierKind: AuthIdentifierKind;\n secret: string;\n}\n\nexport interface SignInFormProps extends AuthFormBaseProps {\n identifiers?: readonly AuthIdentifierKind[];\n identifierLabel?: React.ReactNode;\n secretLabel?: React.ReactNode;\n forgotPasswordLabel?: React.ReactNode;\n signUpLabel?: React.ReactNode;\n onSubmit: (values: SignInFormValues) => void | Promise<void>;\n onForgotPassword?: () => void | Promise<void>;\n onSignUp?: () => void | Promise<void>;\n}\n\nexport type SignUpFormValues = FormValues;\nexport type SignUpFormField = FormFieldConfig;\n\nexport interface SignUpFormProps extends AuthFormBaseProps {\n fields?: readonly SignUpFormField[];\n signInLabel?: React.ReactNode;\n onSubmit: (values: SignUpFormValues) => void | Promise<void>;\n onSignIn?: () => void | Promise<void>;\n}\n\nexport interface ForgotPasswordFormValues {\n identifier: string;\n identifierKind: AuthIdentifierKind;\n}\n\nexport interface ForgotPasswordFormProps extends AuthFormBaseProps {\n identifiers?: readonly AuthIdentifierKind[];\n identifierLabel?: React.ReactNode;\n signInLabel?: React.ReactNode;\n onSubmit: (values: ForgotPasswordFormValues) => void | Promise<void>;\n onSignIn?: () => void | Promise<void>;\n}\n\nexport interface OtpFormValues {\n otp: string;\n}\n\nexport interface OtpFormProps extends AuthFormBaseProps {\n length?: number;\n otpLabel?: React.ReactNode;\n resendLabel?: React.ReactNode;\n resendDisabled?: boolean;\n resendLoading?: boolean;\n onSubmit: (values: OtpFormValues) => void | Promise<void>;\n onResend?: () => void | Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FormFieldConfig, ValidationRule } from '../../components/form';
|
|
2
|
+
import type { AuthIdentifierKind } from './types';
|
|
3
|
+
export declare const defaultIdentifiers: readonly ["email"];
|
|
4
|
+
export declare function resolveIdentifierLabel(identifiers: readonly AuthIdentifierKind[]): string;
|
|
5
|
+
export declare function resolveIdentifierType(identifiers: readonly AuthIdentifierKind[]): FormFieldConfig['type'];
|
|
6
|
+
export declare function resolveIdentifierRules(identifiers: readonly AuthIdentifierKind[]): readonly ValidationRule[];
|
|
7
|
+
export declare function normalizeIdentifierKind(identifier: string, identifiers: readonly AuthIdentifierKind[]): AuthIdentifierKind;
|
|
8
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/patterns/auth/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,eAAO,MAAM,kBAAkB,oBAA6D,CAAC;AAe7F,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAMzF;AAED,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,SAAS,kBAAkB,EAAE,GACzC,eAAe,CAAC,MAAM,CAAC,CAgBzB;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,SAAS,kBAAkB,EAAE,GACzC,SAAS,cAAc,EAAE,CAM3B;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,SAAS,kBAAkB,EAAE,GACzC,kBAAkB,CAoBpB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const defaultIdentifiers = ['email'];
|
|
2
|
+
const identifierLabels = {
|
|
3
|
+
email: 'Email',
|
|
4
|
+
phone: 'Phone',
|
|
5
|
+
username: 'Username',
|
|
6
|
+
};
|
|
7
|
+
function includesIdentifier(identifiers, identifier) {
|
|
8
|
+
return identifiers.includes(identifier);
|
|
9
|
+
}
|
|
10
|
+
export function resolveIdentifierLabel(identifiers) {
|
|
11
|
+
if (identifiers.length === 1) {
|
|
12
|
+
return identifierLabels[identifiers[0] ?? 'email'];
|
|
13
|
+
}
|
|
14
|
+
return identifiers.map((identifier) => identifierLabels[identifier]).join(', or ');
|
|
15
|
+
}
|
|
16
|
+
export function resolveIdentifierType(identifiers) {
|
|
17
|
+
if (identifiers.length !== 1) {
|
|
18
|
+
return 'text';
|
|
19
|
+
}
|
|
20
|
+
const [identifier] = identifiers;
|
|
21
|
+
if (identifier === 'email') {
|
|
22
|
+
return 'email';
|
|
23
|
+
}
|
|
24
|
+
if (identifier === 'phone') {
|
|
25
|
+
return 'tel';
|
|
26
|
+
}
|
|
27
|
+
return 'text';
|
|
28
|
+
}
|
|
29
|
+
export function resolveIdentifierRules(identifiers) {
|
|
30
|
+
if (identifiers.length === 1 && identifiers[0] === 'email') {
|
|
31
|
+
return [{ kind: 'required' }, { kind: 'email' }];
|
|
32
|
+
}
|
|
33
|
+
return [{ kind: 'required' }];
|
|
34
|
+
}
|
|
35
|
+
export function normalizeIdentifierKind(identifier, identifiers) {
|
|
36
|
+
const normalizedIdentifier = identifier.trim();
|
|
37
|
+
if (identifiers.length === 1) {
|
|
38
|
+
return identifiers[0] ?? 'email';
|
|
39
|
+
}
|
|
40
|
+
if (includesIdentifier(identifiers, 'email') && normalizedIdentifier.includes('@')) {
|
|
41
|
+
return 'email';
|
|
42
|
+
}
|
|
43
|
+
if (includesIdentifier(identifiers, 'phone') && /^[+()\d\s.-]+$/.test(normalizedIdentifier)) {
|
|
44
|
+
return 'phone';
|
|
45
|
+
}
|
|
46
|
+
if (includesIdentifier(identifiers, 'username')) {
|
|
47
|
+
return 'username';
|
|
48
|
+
}
|
|
49
|
+
return identifiers[0] ?? 'email';
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/patterns/auth/utils.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAO,CAAkD,CAAC;AAE7F,MAAM,gBAAgB,GAAuC;IAC3D,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,SAAS,kBAAkB,CACzB,WAA0C,EAC1C,UAA8B;IAE9B,OAAO,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,WAA0C;IAC/E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,WAA0C;IAE1C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC;IAEjC,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,WAA0C;IAE1C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QAC3D,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,UAAkB,EAClB,WAA0C;IAE1C,MAAM,oBAAoB,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAE/C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,WAAW,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;IACnC,CAAC;IAED,IAAI,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC5F,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,kBAAkB,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;QAChD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,WAAW,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;AACnC,CAAC","sourcesContent":["import type { FormFieldConfig, ValidationRule } from '../../components/form';\nimport type { AuthIdentifierKind } from './types';\n\nexport const defaultIdentifiers = ['email'] as const satisfies readonly AuthIdentifierKind[];\n\nconst identifierLabels: Record<AuthIdentifierKind, string> = {\n email: 'Email',\n phone: 'Phone',\n username: 'Username',\n};\n\nfunction includesIdentifier(\n identifiers: readonly AuthIdentifierKind[],\n identifier: AuthIdentifierKind,\n): boolean {\n return identifiers.includes(identifier);\n}\n\nexport function resolveIdentifierLabel(identifiers: readonly AuthIdentifierKind[]): string {\n if (identifiers.length === 1) {\n return identifierLabels[identifiers[0] ?? 'email'];\n }\n\n return identifiers.map((identifier) => identifierLabels[identifier]).join(', or ');\n}\n\nexport function resolveIdentifierType(\n identifiers: readonly AuthIdentifierKind[],\n): FormFieldConfig['type'] {\n if (identifiers.length !== 1) {\n return 'text';\n }\n\n const [identifier] = identifiers;\n\n if (identifier === 'email') {\n return 'email';\n }\n\n if (identifier === 'phone') {\n return 'tel';\n }\n\n return 'text';\n}\n\nexport function resolveIdentifierRules(\n identifiers: readonly AuthIdentifierKind[],\n): readonly ValidationRule[] {\n if (identifiers.length === 1 && identifiers[0] === 'email') {\n return [{ kind: 'required' }, { kind: 'email' }];\n }\n\n return [{ kind: 'required' }];\n}\n\nexport function normalizeIdentifierKind(\n identifier: string,\n identifiers: readonly AuthIdentifierKind[],\n): AuthIdentifierKind {\n const normalizedIdentifier = identifier.trim();\n\n if (identifiers.length === 1) {\n return identifiers[0] ?? 'email';\n }\n\n if (includesIdentifier(identifiers, 'email') && normalizedIdentifier.includes('@')) {\n return 'email';\n }\n\n if (includesIdentifier(identifiers, 'phone') && /^[+()\\d\\s.-]+$/.test(normalizedIdentifier)) {\n return 'phone';\n }\n\n if (includesIdentifier(identifiers, 'username')) {\n return 'username';\n }\n\n return identifiers[0] ?? 'email';\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/zora",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.1",
|
|
5
5
|
"description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/zora#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@ankhorage/surface": "^0.1.
|
|
46
|
+
"@ankhorage/surface": "^0.1.11"
|
|
47
47
|
},
|
|
48
48
|
"files": [
|
|
49
49
|
"dist",
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Box, Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { FormActions } from './FormActions';
|
|
5
|
+
import { FormError } from './FormError';
|
|
6
|
+
import { FormField } from './FormField';
|
|
7
|
+
import type { FormProps } from './types';
|
|
8
|
+
import { useFormController } from './useFormController';
|
|
9
|
+
|
|
10
|
+
export function Form<TName extends string = string>({
|
|
11
|
+
fields,
|
|
12
|
+
values,
|
|
13
|
+
onChange,
|
|
14
|
+
onSubmit,
|
|
15
|
+
errors,
|
|
16
|
+
error,
|
|
17
|
+
loading = false,
|
|
18
|
+
disabled = false,
|
|
19
|
+
submitLabel = 'Submit',
|
|
20
|
+
actions,
|
|
21
|
+
footer,
|
|
22
|
+
validateOnChange = false,
|
|
23
|
+
testID,
|
|
24
|
+
}: FormProps<TName>) {
|
|
25
|
+
const controller = useFormController({
|
|
26
|
+
fields,
|
|
27
|
+
values,
|
|
28
|
+
errors,
|
|
29
|
+
onChange,
|
|
30
|
+
onSubmit,
|
|
31
|
+
validateOnChange,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Stack gap="m" testID={testID}>
|
|
36
|
+
<FormError error={error} />
|
|
37
|
+
{fields.map((field) => (
|
|
38
|
+
<FormField
|
|
39
|
+
key={field.name}
|
|
40
|
+
disabled={disabled}
|
|
41
|
+
error={controller.errors[field.name]}
|
|
42
|
+
field={field}
|
|
43
|
+
loading={loading}
|
|
44
|
+
onChange={controller.setFieldValue}
|
|
45
|
+
value={values[field.name]}
|
|
46
|
+
/>
|
|
47
|
+
))}
|
|
48
|
+
<FormActions
|
|
49
|
+
disabled={disabled}
|
|
50
|
+
loading={loading}
|
|
51
|
+
onSubmit={() => {
|
|
52
|
+
void controller.handleSubmit();
|
|
53
|
+
}}
|
|
54
|
+
submitLabel={submitLabel}
|
|
55
|
+
>
|
|
56
|
+
{actions}
|
|
57
|
+
</FormActions>
|
|
58
|
+
{footer ? <Box>{footer}</Box> : null}
|
|
59
|
+
</Stack>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Box, Stack } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { Button } from '../button';
|
|
5
|
+
import type { FormActionsProps } from './types';
|
|
6
|
+
|
|
7
|
+
export function FormActions({
|
|
8
|
+
submitLabel = 'Submit',
|
|
9
|
+
loading = false,
|
|
10
|
+
disabled = false,
|
|
11
|
+
onSubmit,
|
|
12
|
+
children,
|
|
13
|
+
testID,
|
|
14
|
+
}: FormActionsProps) {
|
|
15
|
+
return (
|
|
16
|
+
<Stack gap="s" testID={testID}>
|
|
17
|
+
<Button disabled={disabled} fullWidth loading={loading} onPress={onSubmit}>
|
|
18
|
+
{submitLabel}
|
|
19
|
+
</Button>
|
|
20
|
+
{children ? <Box>{children}</Box> : null}
|
|
21
|
+
</Stack>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Box, Text, useTheme } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { FormErrorProps } from './types';
|
|
5
|
+
|
|
6
|
+
export function FormError({ error, testID }: FormErrorProps) {
|
|
7
|
+
const { theme } = useTheme();
|
|
8
|
+
|
|
9
|
+
if (!error) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Box borderColor={theme.colors.error} borderWidth={1} p="s" radius="m" testID={testID}>
|
|
15
|
+
<Text color={theme.colors.error} variant="bodySmall">
|
|
16
|
+
{error}
|
|
17
|
+
</Text>
|
|
18
|
+
</Box>
|
|
19
|
+
);
|
|
20
|
+
}
|