@ankhorage/zora 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +267 -283
  3. package/dist/components/form/Form.d.ts +4 -0
  4. package/dist/components/form/Form.d.ts.map +1 -0
  5. package/dist/components/form/Form.js +27 -0
  6. package/dist/components/form/Form.js.map +1 -0
  7. package/dist/components/form/FormActions.d.ts +4 -0
  8. package/dist/components/form/FormActions.d.ts.map +1 -0
  9. package/dist/components/form/FormActions.js +12 -0
  10. package/dist/components/form/FormActions.js.map +1 -0
  11. package/dist/components/form/FormError.d.ts +4 -0
  12. package/dist/components/form/FormError.d.ts.map +1 -0
  13. package/dist/components/form/FormError.js +14 -0
  14. package/dist/components/form/FormError.js.map +1 -0
  15. package/dist/components/form/FormField.d.ts +4 -0
  16. package/dist/components/form/FormField.d.ts.map +1 -0
  17. package/dist/components/form/FormField.js +74 -0
  18. package/dist/components/form/FormField.js.map +1 -0
  19. package/dist/components/form/index.d.ts +8 -0
  20. package/dist/components/form/index.d.ts.map +1 -0
  21. package/dist/components/form/index.js +7 -0
  22. package/dist/components/form/index.js.map +1 -0
  23. package/dist/components/form/types.d.ts +107 -0
  24. package/dist/components/form/types.d.ts.map +1 -0
  25. package/dist/components/form/types.js +2 -0
  26. package/dist/components/form/types.js.map +1 -0
  27. package/dist/components/form/useFormController.d.ts +3 -0
  28. package/dist/components/form/useFormController.d.ts.map +1 -0
  29. package/dist/components/form/useFormController.js +62 -0
  30. package/dist/components/form/useFormController.js.map +1 -0
  31. package/dist/components/form/validation.d.ts +6 -0
  32. package/dist/components/form/validation.d.ts.map +1 -0
  33. package/dist/components/form/validation.js +52 -0
  34. package/dist/components/form/validation.js.map +1 -0
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/patterns/auth/ForgotPasswordForm.d.ts +4 -0
  40. package/dist/patterns/auth/ForgotPasswordForm.d.ts.map +1 -0
  41. package/dist/patterns/auth/ForgotPasswordForm.js +31 -0
  42. package/dist/patterns/auth/ForgotPasswordForm.js.map +1 -0
  43. package/dist/patterns/auth/OtpForm.d.ts +4 -0
  44. package/dist/patterns/auth/OtpForm.d.ts.map +1 -0
  45. package/dist/patterns/auth/OtpForm.js +30 -0
  46. package/dist/patterns/auth/OtpForm.js.map +1 -0
  47. package/dist/patterns/auth/SignInForm.d.ts +4 -0
  48. package/dist/patterns/auth/SignInForm.d.ts.map +1 -0
  49. package/dist/patterns/auth/SignInForm.js +45 -0
  50. package/dist/patterns/auth/SignInForm.js.map +1 -0
  51. package/dist/patterns/auth/SignUpForm.d.ts +4 -0
  52. package/dist/patterns/auth/SignUpForm.d.ts.map +1 -0
  53. package/dist/patterns/auth/SignUpForm.js +37 -0
  54. package/dist/patterns/auth/SignUpForm.js.map +1 -0
  55. package/dist/patterns/auth/index.d.ts +6 -0
  56. package/dist/patterns/auth/index.d.ts.map +1 -0
  57. package/dist/patterns/auth/index.js +5 -0
  58. package/dist/patterns/auth/index.js.map +1 -0
  59. package/dist/patterns/auth/types.d.ts +57 -0
  60. package/dist/patterns/auth/types.d.ts.map +1 -0
  61. package/dist/patterns/auth/types.js +2 -0
  62. package/dist/patterns/auth/types.js.map +1 -0
  63. package/dist/patterns/auth/utils.d.ts +8 -0
  64. package/dist/patterns/auth/utils.d.ts.map +1 -0
  65. package/dist/patterns/auth/utils.js +51 -0
  66. package/dist/patterns/auth/utils.js.map +1 -0
  67. package/package.json +2 -2
  68. package/src/components/form/Form.tsx +61 -0
  69. package/src/components/form/FormActions.tsx +23 -0
  70. package/src/components/form/FormError.tsx +20 -0
  71. package/src/components/form/FormField.tsx +128 -0
  72. package/src/components/form/index.ts +24 -0
  73. package/src/components/form/types.ts +115 -0
  74. package/src/components/form/useFormController.ts +105 -0
  75. package/src/components/form/validation.test.ts +79 -0
  76. package/src/components/form/validation.ts +83 -0
  77. package/src/index.ts +43 -2
  78. package/src/patterns/auth/ForgotPasswordForm.tsx +84 -0
  79. package/src/patterns/auth/OtpForm.tsx +80 -0
  80. package/src/patterns/auth/SignInForm.tsx +111 -0
  81. package/src/patterns/auth/SignUpForm.tsx +76 -0
  82. package/src/patterns/auth/index.ts +17 -0
  83. package/src/patterns/auth/types.ts +67 -0
  84. package/src/patterns/auth/utils.ts +80 -0
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;AAE7C,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;AAKtD,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,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,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 { 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 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 { FormFieldProps } from './patterns/form-field';\nexport { FormField } from './patterns/form-field';\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"]}
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,5 @@
1
+ export { ForgotPasswordForm } from './ForgotPasswordForm';
2
+ export { OtpForm } from './OtpForm';
3
+ export { SignInForm } from './SignInForm';
4
+ export { SignUpForm } from './SignUpForm';
5
+ //# sourceMappingURL=index.js.map
@@ -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":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,kBAAkB,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC5C,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACtC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,gBAAgB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAC1C,MAAM,MAAM,eAAe,GAAG,eAAe,CAAC;AAE9C,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,kBAAkB,CAAC;CACpC;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC5C,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -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.5.2",
4
+ "version": "0.6.0",
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.9"
46
+ "@ankhorage/surface": "^0.1.10"
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
+ }