@terreno/ui 0.0.18 → 0.2.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.
- package/dist/Button.js +1 -1
- package/dist/Button.js.map +1 -1
- package/dist/Common.d.ts +45 -1
- package/dist/Hyperlink.js +2 -2
- package/dist/Hyperlink.js.map +1 -1
- package/dist/Page.js +2 -1
- package/dist/Page.js.map +1 -1
- package/dist/SocialLoginButton.d.ts +19 -0
- package/dist/SocialLoginButton.js +119 -0
- package/dist/SocialLoginButton.js.map +1 -0
- package/dist/Text.js +3 -0
- package/dist/Text.js.map +1 -1
- package/dist/Theme.js +27 -27
- package/dist/Theme.js.map +1 -1
- package/dist/Toast.js +5 -2
- package/dist/Toast.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/login/LoginScreen.d.ts +25 -0
- package/dist/login/LoginScreen.js +55 -0
- package/dist/login/LoginScreen.js.map +1 -0
- package/dist/login/index.d.ts +2 -0
- package/dist/login/index.js +2 -0
- package/dist/login/index.js.map +1 -0
- package/dist/login/loginTypes.d.ts +48 -0
- package/dist/login/loginTypes.js +2 -0
- package/dist/login/loginTypes.js.map +1 -0
- package/dist/signUp/OAuthButtons.d.ts +18 -0
- package/dist/signUp/OAuthButtons.js +15 -0
- package/dist/signUp/OAuthButtons.js.map +1 -0
- package/dist/signUp/PasswordRequirements.d.ts +15 -0
- package/dist/signUp/PasswordRequirements.js +14 -0
- package/dist/signUp/PasswordRequirements.js.map +1 -0
- package/dist/signUp/SignUpScreen.d.ts +26 -0
- package/dist/signUp/SignUpScreen.js +64 -0
- package/dist/signUp/SignUpScreen.js.map +1 -0
- package/dist/signUp/Swiper.d.ts +13 -0
- package/dist/signUp/Swiper.js +16 -0
- package/dist/signUp/Swiper.js.map +1 -0
- package/dist/signUp/index.d.ts +6 -0
- package/dist/signUp/index.js +6 -0
- package/dist/signUp/index.js.map +1 -0
- package/dist/signUp/passwordPresets.d.ts +9 -0
- package/dist/signUp/passwordPresets.js +41 -0
- package/dist/signUp/passwordPresets.js.map +1 -0
- package/dist/signUp/signUpTypes.d.ts +90 -0
- package/dist/signUp/signUpTypes.js +2 -0
- package/dist/signUp/signUpTypes.js.map +1 -0
- package/package.json +10 -7
- package/src/Button.tsx +1 -1
- package/src/Common.ts +53 -2
- package/src/Hyperlink.tsx +2 -10
- package/src/Page.tsx +3 -2
- package/src/SocialLoginButton.test.tsx +158 -0
- package/src/SocialLoginButton.tsx +182 -0
- package/src/Text.tsx +3 -0
- package/src/Theme.tsx +33 -27
- package/src/Toast.tsx +5 -2
- package/src/__snapshots__/Button.test.tsx.snap +12 -12
- package/src/__snapshots__/DecimalRangeActionSheet.test.tsx.snap +2 -2
- package/src/__snapshots__/ErrorPage.test.tsx.snap +1 -1
- package/src/__snapshots__/Field.test.tsx.snap +138 -138
- package/src/__snapshots__/HeightActionSheet.test.tsx.snap +2 -2
- package/src/__snapshots__/InfoModalIcon.test.tsx.snap +4 -4
- package/src/__snapshots__/Modal.test.tsx.snap +3 -3
- package/src/__snapshots__/NumberPickerActionSheet.test.tsx.snap +2 -2
- package/src/__snapshots__/Page.test.tsx.snap +1 -1
- package/src/__snapshots__/PhoneNumberField.test.tsx.snap +17 -17
- package/src/__snapshots__/SocialLoginButton.test.tsx.snap +277 -0
- package/src/bunSetup.ts +23 -0
- package/src/index.tsx +6 -0
- package/src/login/LoginScreen.test.tsx +148 -0
- package/src/login/LoginScreen.tsx +159 -0
- package/src/login/__snapshots__/LoginScreen.test.tsx.snap +630 -0
- package/src/login/index.ts +2 -0
- package/src/login/loginTypes.ts +51 -0
- package/src/signUp/OAuthButtons.test.tsx +45 -0
- package/src/signUp/OAuthButtons.tsx +52 -0
- package/src/signUp/PasswordRequirements.test.tsx +41 -0
- package/src/signUp/PasswordRequirements.tsx +49 -0
- package/src/signUp/SignUpScreen.test.tsx +134 -0
- package/src/signUp/SignUpScreen.tsx +172 -0
- package/src/signUp/Swiper.test.tsx +46 -0
- package/src/signUp/Swiper.tsx +59 -0
- package/src/signUp/__snapshots__/OAuthButtons.test.tsx.snap +272 -0
- package/src/signUp/__snapshots__/PasswordRequirements.test.tsx.snap +427 -0
- package/src/signUp/__snapshots__/SignUpScreen.test.tsx.snap +851 -0
- package/src/signUp/__snapshots__/Swiper.test.tsx.snap +249 -0
- package/src/signUp/index.ts +13 -0
- package/src/signUp/passwordPresets.test.ts +57 -0
- package/src/signUp/passwordPresets.ts +43 -0
- package/src/signUp/signUpTypes.ts +94 -0
- package/src/table/__snapshots__/TableDate.test.tsx.snap +4 -4
- package/src/table/__snapshots__/TableRow.test.tsx.snap +64 -64
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
import { Box } from "../Box";
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Heading } from "../Heading";
|
|
6
|
+
import { Page } from "../Page";
|
|
7
|
+
import { OAuthButtons } from "../signUp/OAuthButtons";
|
|
8
|
+
import { Text } from "../Text";
|
|
9
|
+
import { TextField } from "../TextField";
|
|
10
|
+
/**
|
|
11
|
+
* A configurable login screen component with support for custom fields,
|
|
12
|
+
* OAuth providers, sign-up link, and forgot password link.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <LoginScreen
|
|
17
|
+
* fields={[
|
|
18
|
+
* {name: "email", label: "Email", type: "email", required: true},
|
|
19
|
+
* {name: "password", label: "Password", type: "password", required: true},
|
|
20
|
+
* ]}
|
|
21
|
+
* onSubmit={async (values) => {
|
|
22
|
+
* await signIn(values.email, values.password);
|
|
23
|
+
* }}
|
|
24
|
+
* oauthProviders={[
|
|
25
|
+
* {provider: "google", onPress: () => signInWithSocial("google")},
|
|
26
|
+
* ]}
|
|
27
|
+
* onSignUpPress={() => router.push("/signup")}
|
|
28
|
+
* onForgotPasswordPress={() => router.push("/forgot-password")}
|
|
29
|
+
* />
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const LoginScreen = ({ fields, onSubmit, oauthProviders, logo, title = "Welcome Back", loading = false, error, signUpLinkText = "Need an account? Sign Up", onSignUpPress, forgotPasswordText = "Forgot password?", onForgotPasswordPress, testID = "login-screen", }) => {
|
|
33
|
+
const [formValues, setFormValues] = useState(() => {
|
|
34
|
+
const initial = {};
|
|
35
|
+
for (const field of fields) {
|
|
36
|
+
initial[field.name] = "";
|
|
37
|
+
}
|
|
38
|
+
return initial;
|
|
39
|
+
});
|
|
40
|
+
const handleFieldChange = useCallback((fieldName, value) => {
|
|
41
|
+
setFormValues((prev) => (Object.assign(Object.assign({}, prev), { [fieldName]: value })));
|
|
42
|
+
}, []);
|
|
43
|
+
const handleSubmit = useCallback(async () => {
|
|
44
|
+
await onSubmit(formValues);
|
|
45
|
+
}, [formValues, onSubmit]);
|
|
46
|
+
const requiredFieldsFilled = fields
|
|
47
|
+
.filter((f) => f.required)
|
|
48
|
+
.every((f) => { var _a; return ((_a = formValues[f.name]) !== null && _a !== void 0 ? _a : "").trim().length > 0; });
|
|
49
|
+
const isSubmitDisabled = loading || !requiredFieldsFilled;
|
|
50
|
+
return (_jsx(Page, { navigation: undefined, children: _jsxs(Box, { alignItems: "center", alignSelf: "center", flex: "grow", justifyContent: "center", maxWidth: 400, padding: 4, testID: testID, width: "100%", children: [Boolean(logo) && _jsx(Box, { marginBottom: 6, children: logo }), _jsx(Box, { marginBottom: 8, children: _jsx(Heading, { testID: `${testID}-title`, children: title }) }), _jsxs(Box, { gap: 4, width: "100%", children: [fields.map((field) => {
|
|
51
|
+
var _a;
|
|
52
|
+
return (_jsx(TextField, { autoComplete: field.autoComplete, disabled: loading, onChange: (value) => handleFieldChange(field.name, value), placeholder: (_a = field.placeholder) !== null && _a !== void 0 ? _a : field.label, testID: `${testID}-${field.name}-input`, title: field.label, type: field.type === "email" ? "email" : field.type === "password" ? "password" : "text", value: formValues[field.name] }, field.name));
|
|
53
|
+
}), Boolean(error) && (_jsx(Text, { color: "error", testID: `${testID}-error`, children: error })), _jsx(Box, { marginTop: 4, children: _jsx(Button, { disabled: isSubmitDisabled, fullWidth: true, loading: loading, onClick: handleSubmit, testID: `${testID}-submit-button`, text: "Log In" }) }), Boolean(onForgotPasswordPress) && (_jsx(Box, { alignItems: "center", marginTop: 2, children: _jsx(Button, { disabled: loading, onClick: onForgotPasswordPress, testID: `${testID}-forgot-password`, text: forgotPasswordText, variant: "muted" }) })), Boolean(onSignUpPress) && (_jsx(Box, { marginTop: 2, children: _jsx(Button, { disabled: loading, fullWidth: true, onClick: onSignUpPress, testID: `${testID}-signup-link`, text: signUpLinkText, variant: "outline" }) })), Boolean(oauthProviders && oauthProviders.length > 0) && (_jsx(OAuthButtons, { disabled: loading, providers: oauthProviders, testID: `${testID}-oauth` }))] })] }) }));
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=LoginScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginScreen.js","sourceRoot":"","sources":["../../src/login/LoginScreen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/login/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { OAuthProviderConfig } from "../signUp/signUpTypes";
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for a login form field.
|
|
5
|
+
*/
|
|
6
|
+
export interface LoginFieldConfig {
|
|
7
|
+
/** Unique field name used as the key in form state. */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Display label for the field. */
|
|
10
|
+
label: string;
|
|
11
|
+
/** Placeholder text shown when the field is empty. */
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
/** Input type for the field. */
|
|
14
|
+
type?: "text" | "email" | "password";
|
|
15
|
+
/** Whether the field is required. */
|
|
16
|
+
required?: boolean;
|
|
17
|
+
/** Auto-complete hint for the field. */
|
|
18
|
+
autoComplete?: "current-password" | "on" | "off" | "username";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Props for the LoginScreen component.
|
|
22
|
+
*/
|
|
23
|
+
export interface LoginScreenProps {
|
|
24
|
+
/** Form field configurations. */
|
|
25
|
+
fields: LoginFieldConfig[];
|
|
26
|
+
/** Callback triggered on form submission. Receives field values as a record. */
|
|
27
|
+
onSubmit: (values: Record<string, string>) => Promise<void>;
|
|
28
|
+
/** Optional OAuth provider configurations for social login buttons. */
|
|
29
|
+
oauthProviders?: OAuthProviderConfig[];
|
|
30
|
+
/** Custom logo or banner to display above the form. */
|
|
31
|
+
logo?: ReactNode;
|
|
32
|
+
/** Title text for the login form. */
|
|
33
|
+
title?: string;
|
|
34
|
+
/** Whether the form is in a loading state. */
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
/** Error message to display. */
|
|
37
|
+
error?: string;
|
|
38
|
+
/** Text for the link to navigate to sign up. */
|
|
39
|
+
signUpLinkText?: string;
|
|
40
|
+
/** Callback triggered when the sign-up link is pressed. */
|
|
41
|
+
onSignUpPress?: () => void;
|
|
42
|
+
/** Text for the forgot password link. */
|
|
43
|
+
forgotPasswordText?: string;
|
|
44
|
+
/** Callback triggered when the forgot password link is pressed. */
|
|
45
|
+
onForgotPasswordPress?: () => void;
|
|
46
|
+
/** Test ID for the root element. */
|
|
47
|
+
testID?: string;
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loginTypes.js","sourceRoot":"","sources":["../../src/login/loginTypes.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FC } from "react";
|
|
2
|
+
import type { OAuthProviderConfig } from "./signUpTypes";
|
|
3
|
+
interface OAuthButtonsProps {
|
|
4
|
+
/** OAuth provider configurations. */
|
|
5
|
+
providers: OAuthProviderConfig[];
|
|
6
|
+
/** Whether all buttons should be disabled. */
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
/** Divider text displayed above the OAuth buttons. */
|
|
9
|
+
dividerText?: string;
|
|
10
|
+
/** Test ID prefix for the component. */
|
|
11
|
+
testID?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Renders OAuth provider buttons with an optional divider text.
|
|
15
|
+
* Uses SocialLoginButton for branded provider buttons.
|
|
16
|
+
*/
|
|
17
|
+
export declare const OAuthButtons: FC<OAuthButtonsProps>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "../Box";
|
|
3
|
+
import { SocialLoginButton } from "../SocialLoginButton";
|
|
4
|
+
import { Text } from "../Text";
|
|
5
|
+
/**
|
|
6
|
+
* Renders OAuth provider buttons with an optional divider text.
|
|
7
|
+
* Uses SocialLoginButton for branded provider buttons.
|
|
8
|
+
*/
|
|
9
|
+
export const OAuthButtons = ({ providers, disabled = false, dividerText = "Or continue with", testID = "oauth-buttons", }) => {
|
|
10
|
+
if (providers.length === 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return (_jsxs(Box, { testID: testID, width: "100%", children: [_jsx(Box, { alignItems: "center", marginTop: 6, children: _jsx(Text, { color: "secondaryLight", children: dividerText }) }), _jsx(Box, { gap: 3, marginTop: 4, children: providers.map((config) => (_jsx(SocialLoginButton, { disabled: disabled || config.disabled, loading: config.loading, onPress: config.onPress, provider: config.provider, testID: `${testID}-${config.provider}` }, config.provider))) })] }));
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=OAuthButtons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthButtons.js","sourceRoot":"","sources":["../../src/signUp/OAuthButtons.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAC,GAAG,EAAC,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAc7B;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAA0B,CAAC,EAClD,SAAS,EACT,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,kBAAkB,EAChC,MAAM,GAAG,eAAe,GACzB,EAAE,EAAE;IACH,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAC,MAAM,aAC/B,KAAC,GAAG,IAAC,UAAU,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,YACnC,KAAC,IAAI,IAAC,KAAK,EAAC,gBAAgB,YAAE,WAAW,GAAQ,GAC7C,EACN,KAAC,GAAG,IAAC,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,YACtB,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACzB,KAAC,iBAAiB,IAChB,QAAQ,EAAE,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAErC,OAAO,EAAE,MAAM,CAAC,OAAO,EACvB,OAAO,EAAE,MAAM,CAAC,OAAO,EACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,IAJjC,MAAM,CAAC,QAAQ,CAKpB,CACH,CAAC,GACE,IACF,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FC } from "react";
|
|
2
|
+
import type { PasswordRequirement } from "./signUpTypes";
|
|
3
|
+
interface PasswordRequirementsProps {
|
|
4
|
+
/** The current password value to validate against. */
|
|
5
|
+
password: string;
|
|
6
|
+
/** List of password requirements to display. */
|
|
7
|
+
requirements: PasswordRequirement[];
|
|
8
|
+
/** Test ID prefix for the component. */
|
|
9
|
+
testID?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Displays a list of password requirements with check/cross indicators.
|
|
13
|
+
*/
|
|
14
|
+
export declare const PasswordRequirements: FC<PasswordRequirementsProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { Icon } from "../Icon";
|
|
4
|
+
import { Text } from "../Text";
|
|
5
|
+
/**
|
|
6
|
+
* Displays a list of password requirements with check/cross indicators.
|
|
7
|
+
*/
|
|
8
|
+
export const PasswordRequirements = ({ password, requirements, testID = "password-requirements", }) => {
|
|
9
|
+
return (_jsx(View, { testID: testID, children: requirements.map((req) => {
|
|
10
|
+
const isMet = password.length > 0 && req.validate(password);
|
|
11
|
+
return (_jsxs(View, { style: { alignItems: "center", flexDirection: "row", gap: 8, marginBottom: 4 }, testID: `${testID}-${req.key}`, children: [_jsx(Icon, { color: isMet ? "success" : "secondaryLight", iconName: isMet ? "circle-check" : "circle", size: "sm", testID: `${testID}-${req.key}-icon` }), _jsx(Text, { color: isMet ? "success" : "secondaryLight", size: "sm", children: req.label })] }, req.key));
|
|
12
|
+
}) }));
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=PasswordRequirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordRequirements.js","sourceRoot":"","sources":["../../src/signUp/PasswordRequirements.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAC;AAElC,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAY7B;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAkC,CAAC,EAClE,QAAQ,EACR,YAAY,EACZ,MAAM,GAAG,uBAAuB,GACjC,EAAE,EAAE;IACH,OAAO,CACL,KAAC,IAAI,IAAC,MAAM,EAAE,MAAM,YACjB,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC5D,OAAO,CACL,MAAC,IAAI,IAEH,KAAK,EAAE,EAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAC,EAC5E,MAAM,EAAE,GAAG,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,aAE9B,KAAC,IAAI,IACH,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,EAC3C,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,EAC3C,IAAI,EAAC,IAAI,EACT,MAAM,EAAE,GAAG,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,GACnC,EACF,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,EAAE,IAAI,EAAC,IAAI,YACzD,GAAG,CAAC,KAAK,GACL,KAZF,GAAG,CAAC,GAAG,CAaP,CACR,CAAC;QACJ,CAAC,CAAC,GACG,CACR,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FC } from "react";
|
|
2
|
+
import type { SignUpScreenProps } from "./signUpTypes";
|
|
3
|
+
/**
|
|
4
|
+
* A configurable sign-up screen component with support for custom fields,
|
|
5
|
+
* password requirements, OAuth providers, and onboarding pages.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <SignUpScreen
|
|
10
|
+
* fields={[
|
|
11
|
+
* {name: "name", label: "Name", type: "text", required: true},
|
|
12
|
+
* {name: "email", label: "Email", type: "email", required: true},
|
|
13
|
+
* {name: "password", label: "Password", type: "password", required: true},
|
|
14
|
+
* ]}
|
|
15
|
+
* onSubmit={async (values) => {
|
|
16
|
+
* await signUp(values.email, values.password, values.name);
|
|
17
|
+
* }}
|
|
18
|
+
* passwordRequirements={defaultPasswordRequirements}
|
|
19
|
+
* oauthProviders={[
|
|
20
|
+
* {provider: "google", onPress: () => signInWithSocial("google")},
|
|
21
|
+
* ]}
|
|
22
|
+
* onLoginPress={() => router.push("/login")}
|
|
23
|
+
* />
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const SignUpScreen: FC<SignUpScreenProps>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
import { Box } from "../Box";
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Heading } from "../Heading";
|
|
6
|
+
import { Page } from "../Page";
|
|
7
|
+
import { Text } from "../Text";
|
|
8
|
+
import { TextField } from "../TextField";
|
|
9
|
+
import { OAuthButtons } from "./OAuthButtons";
|
|
10
|
+
import { PasswordRequirements } from "./PasswordRequirements";
|
|
11
|
+
import { Swiper } from "./Swiper";
|
|
12
|
+
/**
|
|
13
|
+
* A configurable sign-up screen component with support for custom fields,
|
|
14
|
+
* password requirements, OAuth providers, and onboarding pages.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <SignUpScreen
|
|
19
|
+
* fields={[
|
|
20
|
+
* {name: "name", label: "Name", type: "text", required: true},
|
|
21
|
+
* {name: "email", label: "Email", type: "email", required: true},
|
|
22
|
+
* {name: "password", label: "Password", type: "password", required: true},
|
|
23
|
+
* ]}
|
|
24
|
+
* onSubmit={async (values) => {
|
|
25
|
+
* await signUp(values.email, values.password, values.name);
|
|
26
|
+
* }}
|
|
27
|
+
* passwordRequirements={defaultPasswordRequirements}
|
|
28
|
+
* oauthProviders={[
|
|
29
|
+
* {provider: "google", onPress: () => signInWithSocial("google")},
|
|
30
|
+
* ]}
|
|
31
|
+
* onLoginPress={() => router.push("/login")}
|
|
32
|
+
* />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const SignUpScreen = ({ fields, onSubmit, oauthProviders, passwordRequirements, onboardingPages, logo, title = "Create Account", loading = false, error, loginLinkText = "Already have an account? Log in", onLoginPress, testID = "signup-screen", }) => {
|
|
36
|
+
var _a;
|
|
37
|
+
const [formValues, setFormValues] = useState(() => {
|
|
38
|
+
const initial = {};
|
|
39
|
+
for (const field of fields) {
|
|
40
|
+
initial[field.name] = "";
|
|
41
|
+
}
|
|
42
|
+
return initial;
|
|
43
|
+
});
|
|
44
|
+
const handleFieldChange = useCallback((fieldName, value) => {
|
|
45
|
+
setFormValues((prev) => (Object.assign(Object.assign({}, prev), { [fieldName]: value })));
|
|
46
|
+
}, []);
|
|
47
|
+
const handleSubmit = useCallback(async () => {
|
|
48
|
+
await onSubmit(formValues);
|
|
49
|
+
}, [formValues, onSubmit]);
|
|
50
|
+
const passwordField = fields.find((f) => f.type === "password");
|
|
51
|
+
const passwordValue = passwordField ? ((_a = formValues[passwordField.name]) !== null && _a !== void 0 ? _a : "") : "";
|
|
52
|
+
const allRequirementsMet = !passwordRequirements ||
|
|
53
|
+
passwordRequirements.length === 0 ||
|
|
54
|
+
passwordRequirements.every((req) => req.validate(passwordValue));
|
|
55
|
+
const requiredFieldsFilled = fields
|
|
56
|
+
.filter((f) => f.required)
|
|
57
|
+
.every((f) => { var _a; return ((_a = formValues[f.name]) !== null && _a !== void 0 ? _a : "").trim().length > 0; });
|
|
58
|
+
const isSubmitDisabled = loading || !requiredFieldsFilled || !allRequirementsMet;
|
|
59
|
+
return (_jsx(Page, { navigation: undefined, children: _jsxs(Box, { alignItems: "center", alignSelf: "center", flex: "grow", justifyContent: "center", maxWidth: 400, padding: 4, testID: testID, width: "100%", children: [Boolean(onboardingPages && onboardingPages.length > 0) && (_jsx(Box, { marginBottom: 6, children: _jsx(Swiper, { pages: onboardingPages, testID: `${testID}-swiper` }) })), Boolean(logo) && _jsx(Box, { marginBottom: 6, children: logo }), _jsx(Box, { marginBottom: 8, children: _jsx(Heading, { testID: `${testID}-title`, children: title }) }), _jsxs(Box, { gap: 4, width: "100%", children: [fields.map((field) => {
|
|
60
|
+
var _a;
|
|
61
|
+
return (_jsx(TextField, { autoComplete: field.autoComplete, disabled: loading, onChange: (value) => handleFieldChange(field.name, value), placeholder: (_a = field.placeholder) !== null && _a !== void 0 ? _a : field.label, testID: `${testID}-${field.name}-input`, title: field.label, type: field.type === "email" ? "email" : field.type === "password" ? "password" : "text", value: formValues[field.name] }, field.name));
|
|
62
|
+
}), Boolean(passwordRequirements && passwordRequirements.length > 0 && passwordField) && (_jsx(PasswordRequirements, { password: passwordValue, requirements: passwordRequirements, testID: `${testID}-password-requirements` })), Boolean(error) && (_jsx(Text, { color: "error", testID: `${testID}-error`, children: error })), _jsx(Box, { marginTop: 4, children: _jsx(Button, { disabled: isSubmitDisabled, fullWidth: true, loading: loading, onClick: handleSubmit, testID: `${testID}-submit-button`, text: "Sign Up" }) }), Boolean(onLoginPress) && (_jsx(Box, { marginTop: 2, children: _jsx(Button, { disabled: loading, fullWidth: true, onClick: onLoginPress, testID: `${testID}-login-link`, text: loginLinkText, variant: "outline" }) })), Boolean(oauthProviders && oauthProviders.length > 0) && (_jsx(OAuthButtons, { disabled: loading, providers: oauthProviders, testID: `${testID}-oauth` }))] })] }) }));
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=SignUpScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignUpScreen.js","sourceRoot":"","sources":["../../src/signUp/SignUpScreen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FC } from "react";
|
|
2
|
+
import type { OnboardingPage } from "./signUpTypes";
|
|
3
|
+
interface SwiperProps {
|
|
4
|
+
/** Onboarding pages to display. */
|
|
5
|
+
pages: OnboardingPage[];
|
|
6
|
+
/** Test ID prefix for the component. */
|
|
7
|
+
testID?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* An onboarding swiper that displays pages with optional images, titles, and subtitles.
|
|
11
|
+
*/
|
|
12
|
+
export declare const Swiper: FC<SwiperProps>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Image } from "react-native";
|
|
3
|
+
import { SwiperFlatList } from "react-native-swiper-flatlist";
|
|
4
|
+
import { Box } from "../Box";
|
|
5
|
+
import { Heading } from "../Heading";
|
|
6
|
+
import { Text } from "../Text";
|
|
7
|
+
/**
|
|
8
|
+
* An onboarding swiper that displays pages with optional images, titles, and subtitles.
|
|
9
|
+
*/
|
|
10
|
+
export const Swiper = ({ pages, testID = "onboarding-swiper" }) => {
|
|
11
|
+
if (pages.length === 0) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return (_jsx(Box, { height: 300, testID: testID, width: "100%", children: _jsx(SwiperFlatList, { autoplay: true, autoplayDelay: 4, autoplayLoop: true, showPagination: true, children: pages.map((page, index) => (_jsxs(Box, { alignItems: "center", justifyContent: "center", padding: 4, width: "100%", children: [Boolean(page.image) && (_jsx(Image, { resizeMode: "contain", source: page.image, style: { height: 120, marginBottom: 16, width: 120 } })), Boolean(page.content) && page.content, _jsx(Heading, { align: "center", size: "md", children: page.title }), Boolean(page.subtitle) && (_jsx(Box, { marginTop: 2, children: _jsx(Text, { align: "center", color: "secondaryLight", children: page.subtitle }) }))] }, `${page.title}-${index}`))) }) }));
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=Swiper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Swiper.js","sourceRoot":"","sources":["../../src/signUp/Swiper.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAC;AACnC,OAAO,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAE5D,OAAO,EAAC,GAAG,EAAC,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AACnC,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAU7B;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAoB,CAAC,EAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAC,EAAE,EAAE;IAC/E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,KAAC,GAAG,IAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAC,MAAM,YAC5C,KAAC,cAAc,IAAC,QAAQ,QAAC,aAAa,EAAE,CAAC,EAAE,YAAY,QAAC,cAAc,kBACnE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,MAAC,GAAG,IACF,UAAU,EAAC,QAAQ,EACnB,cAAc,EAAC,QAAQ,EAEvB,OAAO,EAAE,CAAC,EACV,KAAK,EAAC,MAAM,aAEX,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CACtB,KAAC,KAAK,IACJ,UAAU,EAAC,SAAS,EACpB,MAAM,EAAE,IAAI,CAAC,KAAM,EACnB,KAAK,EAAE,EAAC,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAC,GAClD,CACH,EACA,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EACtC,KAAC,OAAO,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,IAAI,YAC9B,IAAI,CAAC,KAAK,GACH,EACT,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CACzB,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,KAAK,EAAC,gBAAgB,YACxC,IAAI,CAAC,QAAQ,GACT,GACH,CACP,KArBI,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,EAAE,CAsBzB,CACP,CAAC,GACa,GACb,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { OAuthButtons } from "./OAuthButtons";
|
|
2
|
+
export { PasswordRequirements } from "./PasswordRequirements";
|
|
3
|
+
export { defaultPasswordRequirements, simplePasswordRequirements } from "./passwordPresets";
|
|
4
|
+
export { SignUpScreen } from "./SignUpScreen";
|
|
5
|
+
export { Swiper } from "./Swiper";
|
|
6
|
+
export type { OAuthProvider, OAuthProviderConfig, OnboardingPage, PasswordRequirement, SignUpFieldConfig, SignUpScreenProps, } from "./signUpTypes";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { OAuthButtons } from "./OAuthButtons";
|
|
2
|
+
export { PasswordRequirements } from "./PasswordRequirements";
|
|
3
|
+
export { defaultPasswordRequirements, simplePasswordRequirements } from "./passwordPresets";
|
|
4
|
+
export { SignUpScreen } from "./SignUpScreen";
|
|
5
|
+
export { Swiper } from "./Swiper";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signUp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAC,2BAA2B,EAAE,0BAA0B,EAAC,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PasswordRequirement } from "./signUpTypes";
|
|
2
|
+
/**
|
|
3
|
+
* Default password requirements with strong validation rules.
|
|
4
|
+
*/
|
|
5
|
+
export declare const defaultPasswordRequirements: PasswordRequirement[];
|
|
6
|
+
/**
|
|
7
|
+
* Simple password requirements with minimal validation.
|
|
8
|
+
*/
|
|
9
|
+
export declare const simplePasswordRequirements: PasswordRequirement[];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default password requirements with strong validation rules.
|
|
3
|
+
*/
|
|
4
|
+
export const defaultPasswordRequirements = [
|
|
5
|
+
{
|
|
6
|
+
key: "minLength",
|
|
7
|
+
label: "At least 8 characters",
|
|
8
|
+
validate: (password) => password.length >= 8,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: "uppercase",
|
|
12
|
+
label: "At least one uppercase letter",
|
|
13
|
+
validate: (password) => /[A-Z]/.test(password),
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
key: "lowercase",
|
|
17
|
+
label: "At least one lowercase letter",
|
|
18
|
+
validate: (password) => /[a-z]/.test(password),
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
key: "number",
|
|
22
|
+
label: "At least one number",
|
|
23
|
+
validate: (password) => /\d/.test(password),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
key: "special",
|
|
27
|
+
label: "At least one special character",
|
|
28
|
+
validate: (password) => /[!@#$%^&*(),.?":{}|<>]/.test(password),
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* Simple password requirements with minimal validation.
|
|
33
|
+
*/
|
|
34
|
+
export const simplePasswordRequirements = [
|
|
35
|
+
{
|
|
36
|
+
key: "minLength",
|
|
37
|
+
label: "At least 6 characters",
|
|
38
|
+
validate: (password) => password.length >= 6,
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
//# sourceMappingURL=passwordPresets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passwordPresets.js","sourceRoot":"","sources":["../../src/signUp/passwordPresets.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAA0B;IAChE;QACE,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,uBAAuB;QAC9B,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;KACrD;IACD;QACE,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,+BAA+B;QACtC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;KACvD;IACD;QACE,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,+BAA+B;QACtC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;KACvD;IACD;QACE,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,qBAAqB;QAC5B,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;KACpD;IACD;QACE,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,gCAAgC;QACvC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC;KACxE;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAA0B;IAC/D;QACE,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,uBAAuB;QAC9B,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;KACrD;CACF,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Supported OAuth providers for social login buttons.
|
|
4
|
+
*/
|
|
5
|
+
export type OAuthProvider = "google" | "github" | "apple";
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for an OAuth provider button.
|
|
8
|
+
*/
|
|
9
|
+
export interface OAuthProviderConfig {
|
|
10
|
+
/** The OAuth provider identifier. */
|
|
11
|
+
provider: OAuthProvider;
|
|
12
|
+
/** Callback triggered when the provider button is pressed. */
|
|
13
|
+
onPress: () => Promise<void>;
|
|
14
|
+
/** Whether the button is in a loading state. */
|
|
15
|
+
loading?: boolean;
|
|
16
|
+
/** Whether the button is disabled. */
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Configuration for a sign-up form field.
|
|
21
|
+
*/
|
|
22
|
+
export interface SignUpFieldConfig {
|
|
23
|
+
/** Unique field name used as the key in form state. */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Display label for the field. */
|
|
26
|
+
label: string;
|
|
27
|
+
/** Placeholder text shown when the field is empty. */
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
/** Input type for the field. */
|
|
30
|
+
type?: "text" | "email" | "password";
|
|
31
|
+
/** Whether the field is required. */
|
|
32
|
+
required?: boolean;
|
|
33
|
+
/** Auto-complete hint for the field. */
|
|
34
|
+
autoComplete?: "current-password" | "on" | "off" | "username";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A single password requirement with a label and validation function.
|
|
38
|
+
*/
|
|
39
|
+
export interface PasswordRequirement {
|
|
40
|
+
/** Unique key for the requirement. */
|
|
41
|
+
key: string;
|
|
42
|
+
/** Display label for the requirement. */
|
|
43
|
+
label: string;
|
|
44
|
+
/** Returns true if the password meets this requirement. */
|
|
45
|
+
validate: (password: string) => boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Configuration for a single onboarding page in the swiper.
|
|
49
|
+
*/
|
|
50
|
+
export interface OnboardingPage {
|
|
51
|
+
/** Title text displayed on the page. */
|
|
52
|
+
title: string;
|
|
53
|
+
/** Subtitle or description text. */
|
|
54
|
+
subtitle?: string;
|
|
55
|
+
/** Custom content to render on the page. */
|
|
56
|
+
content?: ReactNode;
|
|
57
|
+
/** Image source for the page. */
|
|
58
|
+
image?: number | {
|
|
59
|
+
uri: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Props for the SignUpScreen component.
|
|
64
|
+
*/
|
|
65
|
+
export interface SignUpScreenProps {
|
|
66
|
+
/** Form field configurations. */
|
|
67
|
+
fields: SignUpFieldConfig[];
|
|
68
|
+
/** Callback triggered on form submission. Receives field values as a record. */
|
|
69
|
+
onSubmit: (values: Record<string, string>) => Promise<void>;
|
|
70
|
+
/** Optional OAuth provider configurations for social login buttons. */
|
|
71
|
+
oauthProviders?: OAuthProviderConfig[];
|
|
72
|
+
/** Password requirements to validate against. */
|
|
73
|
+
passwordRequirements?: PasswordRequirement[];
|
|
74
|
+
/** Onboarding pages to display before the sign-up form. */
|
|
75
|
+
onboardingPages?: OnboardingPage[];
|
|
76
|
+
/** Custom logo or banner to display above the form. */
|
|
77
|
+
logo?: ReactNode;
|
|
78
|
+
/** Title text for the sign-up form. */
|
|
79
|
+
title?: string;
|
|
80
|
+
/** Whether the form is in a loading state. */
|
|
81
|
+
loading?: boolean;
|
|
82
|
+
/** Error message to display. */
|
|
83
|
+
error?: string;
|
|
84
|
+
/** Text for the link to navigate to login. */
|
|
85
|
+
loginLinkText?: string;
|
|
86
|
+
/** Callback triggered when the login link is pressed. */
|
|
87
|
+
onLoginPress?: () => void;
|
|
88
|
+
/** Test ID for the root element. */
|
|
89
|
+
testID?: string;
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signUpTypes.js","sourceRoot":"","sources":["../../src/signUp/signUpTypes.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
"expo-splash-screen": "~31.0.12",
|
|
40
40
|
"expo-updates": "^29.0.15",
|
|
41
41
|
"expo-web-browser": "~15.0.10",
|
|
42
|
-
"libphonenumber-js": "^1.12.
|
|
43
|
-
"
|
|
42
|
+
"libphonenumber-js": "^1.12.36",
|
|
43
|
+
"linkify-it": "^5.0.0",
|
|
44
|
+
"lodash": "^4.17.23",
|
|
44
45
|
"luxon": "^3.7.2",
|
|
45
46
|
"react-app-polyfill": "^3.0.0",
|
|
46
47
|
"react-date-picker": "^12.0.1",
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"react-native-calendars": "^1.1312.1",
|
|
54
55
|
"react-native-drawer-layout": "4.2.0",
|
|
55
56
|
"react-native-gesture-handler": "~2.28.0",
|
|
56
|
-
"react-native-google-places-autocomplete": "^2.6.
|
|
57
|
+
"react-native-google-places-autocomplete": "^2.6.4",
|
|
57
58
|
"react-native-markdown-display": "^7.0.2",
|
|
58
59
|
"react-native-modalize": "^2.1.1",
|
|
59
60
|
"react-native-permissions": "^5.4.4",
|
|
@@ -67,16 +68,16 @@
|
|
|
67
68
|
"react-native-swiper-flatlist": "^3.2.5",
|
|
68
69
|
"react-native-web": "~0.21.0",
|
|
69
70
|
"react-native-webview": "13.15.0",
|
|
70
|
-
"react-native-worklets": "0.
|
|
71
|
+
"react-native-worklets": "~0.7.",
|
|
71
72
|
"react-signature-canvas": "^1.1.0-alpha.2",
|
|
72
|
-
"react-time-picker": "^
|
|
73
|
+
"react-time-picker": "^8.0.2"
|
|
73
74
|
},
|
|
74
75
|
"devDependencies": {
|
|
75
76
|
"@biomejs/biome": "^2.3.6",
|
|
76
77
|
"@expo/config-plugins": "~54.0.4",
|
|
77
78
|
"@happy-dom/global-registrator": "^17.4.4",
|
|
78
79
|
"@testing-library/react-native": "^13.2.0",
|
|
79
|
-
"@types/bun": "^1.
|
|
80
|
+
"@types/bun": "^1.3.8",
|
|
80
81
|
"@types/lodash": "^4.17.17",
|
|
81
82
|
"@types/luxon": "^3.7.1",
|
|
82
83
|
"@types/mdurl": "^2.0.0",
|
|
@@ -92,6 +93,7 @@
|
|
|
92
93
|
"react": "19.1.0",
|
|
93
94
|
"react-router": "^6.26.2",
|
|
94
95
|
"react-router-dom": "^6.30.1",
|
|
96
|
+
"react-test-renderer": "19.1.0",
|
|
95
97
|
"tsc-watch": "^7.1.1",
|
|
96
98
|
"typescript": "~5.9.2"
|
|
97
99
|
},
|
|
@@ -118,6 +120,7 @@
|
|
|
118
120
|
},
|
|
119
121
|
"scripts": {
|
|
120
122
|
"compile": "tsc",
|
|
123
|
+
"compile:watch": "tsc -w",
|
|
121
124
|
"dev": "tsc -w",
|
|
122
125
|
"lint": "biome check .",
|
|
123
126
|
"lint:fix": "biome check --write .",
|
|
@@ -127,5 +130,5 @@
|
|
|
127
130
|
"test:ci": "TZ=America/New_York bun test",
|
|
128
131
|
"types": "bunx typedoc"
|
|
129
132
|
},
|
|
130
|
-
"version": "0.0
|
|
133
|
+
"version": "0.2.0"
|
|
131
134
|
}
|
package/src/Button.tsx
CHANGED
|
@@ -103,7 +103,7 @@ const ButtonComponent: FC<ButtonProps> = ({
|
|
|
103
103
|
)}
|
|
104
104
|
style={{
|
|
105
105
|
alignItems: "center",
|
|
106
|
-
alignSelf: fullWidth ? "stretch" :
|
|
106
|
+
alignSelf: fullWidth ? "stretch" : "flex-start",
|
|
107
107
|
backgroundColor,
|
|
108
108
|
borderColor,
|
|
109
109
|
borderRadius: theme.radius.rounded,
|