@himakarinv/nativex 1.0.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 (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/images.d.ts +14 -0
  4. package/index.js +8 -0
  5. package/nativewind-preset.js +18 -0
  6. package/package.json +120 -0
  7. package/src/assets/branding/logo.jpg +0 -0
  8. package/src/assets/branding/softech-logo.png +0 -0
  9. package/src/assets/icons/2-layers.svg +3 -0
  10. package/src/assets/icons/Forbidden.svg +211 -0
  11. package/src/assets/icons/Internal-server-error.svg +119 -0
  12. package/src/assets/icons/Log-out-nav.svg +4 -0
  13. package/src/assets/icons/Not-Found.svg +282 -0
  14. package/src/assets/icons/Unauthorized.svg +314 -0
  15. package/src/assets/icons/User-Frame.svg +5 -0
  16. package/src/assets/icons/alert.svg +4 -0
  17. package/src/assets/icons/arrow-right.svg +3 -0
  18. package/src/assets/icons/avatar-female.svg +10 -0
  19. package/src/assets/icons/avatar-male.svg +10 -0
  20. package/src/assets/icons/bell.svg +3 -0
  21. package/src/assets/icons/calendar-event.svg +11 -0
  22. package/src/assets/icons/calendar.svg +6 -0
  23. package/src/assets/icons/card.svg +4 -0
  24. package/src/assets/icons/caret-right.svg +3 -0
  25. package/src/assets/icons/chat.svg +11 -0
  26. package/src/assets/icons/check.svg +3 -0
  27. package/src/assets/icons/checkbox-minus.svg +3 -0
  28. package/src/assets/icons/checkmark.svg +3 -0
  29. package/src/assets/icons/chevron-down.svg +3 -0
  30. package/src/assets/icons/chevron-left.svg +9 -0
  31. package/src/assets/icons/chevron-right.svg +9 -0
  32. package/src/assets/icons/circle-radio-active.svg +10 -0
  33. package/src/assets/icons/circle-radio.svg +10 -0
  34. package/src/assets/icons/clock.svg +3 -0
  35. package/src/assets/icons/close.svg +3 -0
  36. package/src/assets/icons/code.svg +3 -0
  37. package/src/assets/icons/country.svg +20 -0
  38. package/src/assets/icons/dot.svg +3 -0
  39. package/src/assets/icons/download.svg +1 -0
  40. package/src/assets/icons/dropdown-arrow.svg +3 -0
  41. package/src/assets/icons/dropdown-avatar.svg +3 -0
  42. package/src/assets/icons/email.svg +3 -0
  43. package/src/assets/icons/error.svg +3 -0
  44. package/src/assets/icons/eye-off.svg +1 -0
  45. package/src/assets/icons/eye.svg +1 -0
  46. package/src/assets/icons/hashtag-icon.svg +3 -0
  47. package/src/assets/icons/help-circle.svg +10 -0
  48. package/src/assets/icons/help.svg +4 -0
  49. package/src/assets/icons/hide-checkbox.svg +3 -0
  50. package/src/assets/icons/home-smile.svg +3 -0
  51. package/src/assets/icons/home.svg +3 -0
  52. package/src/assets/icons/info.svg +5 -0
  53. package/src/assets/icons/left-arrow.svg +3 -0
  54. package/src/assets/icons/log-out.svg +3 -0
  55. package/src/assets/icons/notification-box.svg +4 -0
  56. package/src/assets/icons/pencil.svg +1 -0
  57. package/src/assets/icons/plus.svg +3 -0
  58. package/src/assets/icons/radio-dot.svg +3 -0
  59. package/src/assets/icons/right-arrow.svg +3 -0
  60. package/src/assets/icons/search.svg +3 -0
  61. package/src/assets/icons/settings.svg +11 -0
  62. package/src/assets/icons/slack.svg +17 -0
  63. package/src/assets/icons/slash.svg +3 -0
  64. package/src/assets/icons/success.svg +3 -0
  65. package/src/assets/icons/successicon.svg +5 -0
  66. package/src/assets/icons/three-dot-vertical.svg +5 -0
  67. package/src/assets/icons/trash.svg +1 -0
  68. package/src/assets/icons/trend-down-01.svg +3 -0
  69. package/src/assets/icons/trend-up-01.svg +3 -0
  70. package/src/assets/icons/up-arrow.svg +3 -0
  71. package/src/assets/icons/user-plus.svg +10 -0
  72. package/src/assets/icons/user.svg +3 -0
  73. package/src/assets/icons/users.svg +3 -0
  74. package/src/assets/icons/vertical-dots-true-icon.svg +5 -0
  75. package/src/assets/icons/vertical-line.svg +3 -0
  76. package/src/assets/icons/vertical-three-dots-icon.svg +5 -0
  77. package/src/assets/icons/warning.svg +3 -0
  78. package/src/assets/icons/zap.svg +3 -0
  79. package/src/components/ActionsMenu/ActionsMenu.tsx +314 -0
  80. package/src/components/ActionsMenu/index.ts +2 -0
  81. package/src/components/Alert/Alert.tsx +291 -0
  82. package/src/components/Alert/index.ts +2 -0
  83. package/src/components/Badge/Badge.tsx +230 -0
  84. package/src/components/Badge/index.ts +2 -0
  85. package/src/components/Breadcrumb/Breadcrumb.tsx +364 -0
  86. package/src/components/Breadcrumb/index.ts +7 -0
  87. package/src/components/Button/Button.tsx +584 -0
  88. package/src/components/Button/index.ts +9 -0
  89. package/src/components/Checkbox/Checkbox.tsx +336 -0
  90. package/src/components/Checkbox/index.ts +2 -0
  91. package/src/components/CreatePassword/CreatePassword.tsx +161 -0
  92. package/src/components/CreatePassword/index.ts +2 -0
  93. package/src/components/DataTable/DataTable.tsx +822 -0
  94. package/src/components/DataTable/index.ts +10 -0
  95. package/src/components/Datepicker/Datepicker.tsx +797 -0
  96. package/src/components/Datepicker/index.ts +2 -0
  97. package/src/components/Dropdown/Dropdown.tsx +277 -0
  98. package/src/components/Dropdown/index.ts +7 -0
  99. package/src/components/DropdownMenu/DropdownMenu.tsx +471 -0
  100. package/src/components/DropdownMenu/index.ts +11 -0
  101. package/src/components/DynamicForm/DynamicForm.tsx +741 -0
  102. package/src/components/DynamicForm/index.ts +13 -0
  103. package/src/components/ErrorPages/ErrorPages.tsx +135 -0
  104. package/src/components/ErrorPages/index.ts +2 -0
  105. package/src/components/ForgotPassword/ForgotPassword.tsx +121 -0
  106. package/src/components/ForgotPassword/index.ts +2 -0
  107. package/src/components/HintError/HintError.tsx +37 -0
  108. package/src/components/HintError/index.ts +2 -0
  109. package/src/components/Icon/Icon.tsx +43 -0
  110. package/src/components/Icon/icon-registry.ts +227 -0
  111. package/src/components/Icon/index.ts +3 -0
  112. package/src/components/InputDropdown/InputDropdown.tsx +662 -0
  113. package/src/components/InputDropdown/index.ts +9 -0
  114. package/src/components/InputField/InputField.tsx +527 -0
  115. package/src/components/InputField/index.ts +2 -0
  116. package/src/components/Label/Label.tsx +88 -0
  117. package/src/components/Label/index.ts +2 -0
  118. package/src/components/LoginForm/LoginForm.tsx +158 -0
  119. package/src/components/LoginForm/index.ts +2 -0
  120. package/src/components/LoginShell/LoginShell.tsx +97 -0
  121. package/src/components/LoginShell/RoleCard.tsx +24 -0
  122. package/src/components/LoginShell/SoftechLogo.tsx +24 -0
  123. package/src/components/LoginShell/branding-assets.ts +2 -0
  124. package/src/components/LoginShell/index.ts +20 -0
  125. package/src/components/LoginShell/login-copy.ts +45 -0
  126. package/src/components/LoginShell/loginPageStyles.ts +210 -0
  127. package/src/components/Modals/Modals.tsx +313 -0
  128. package/src/components/Modals/index.ts +2 -0
  129. package/src/components/Offcanvas/Offcanvas.tsx +404 -0
  130. package/src/components/Offcanvas/index.ts +13 -0
  131. package/src/components/PageHeader/PageHeader.tsx +128 -0
  132. package/src/components/PageHeader/index.ts +2 -0
  133. package/src/components/Pagination/Pagination.tsx +540 -0
  134. package/src/components/Pagination/index.ts +8 -0
  135. package/src/components/ResetPassword/ResetPassword.tsx +172 -0
  136. package/src/components/ResetPassword/index.ts +2 -0
  137. package/src/components/RoleSelection/RoleSelection.tsx +111 -0
  138. package/src/components/RoleSelection/index.ts +2 -0
  139. package/src/components/SendOtp/SendOtp.tsx +149 -0
  140. package/src/components/SendOtp/index.ts +2 -0
  141. package/src/components/Sidenavbar/Sidenavbar.tsx +358 -0
  142. package/src/components/Sidenavbar/index.ts +2 -0
  143. package/src/components/StatCard/StatCard.tsx +393 -0
  144. package/src/components/StatCard/index.ts +6 -0
  145. package/src/components/Tabs/Tabs.tsx +239 -0
  146. package/src/components/Tabs/index.ts +2 -0
  147. package/src/components/Textarea/Textarea.tsx +217 -0
  148. package/src/components/Textarea/index.ts +2 -0
  149. package/src/components/Timepicker/Timepicker.tsx +384 -0
  150. package/src/components/Timepicker/index.ts +2 -0
  151. package/src/components/Toast/Toast.tsx +278 -0
  152. package/src/components/Toast/index.ts +2 -0
  153. package/src/components/Toggle/Toggle.tsx +296 -0
  154. package/src/components/Toggle/index.ts +2 -0
  155. package/src/components/Typeahead/Typeahead.tsx +521 -0
  156. package/src/components/Typeahead/index.ts +2 -0
  157. package/src/components/Verification/Verification.tsx +374 -0
  158. package/src/components/Verification/index.ts +2 -0
  159. package/src/index.ts +39 -0
  160. package/src/theme/borders.ts +19 -0
  161. package/src/theme/button.ts +41 -0
  162. package/src/theme/colors.ts +273 -0
  163. package/src/theme/index.ts +14 -0
  164. package/src/theme/nativewind-theme.js +182 -0
  165. package/src/theme/radius.ts +12 -0
  166. package/src/theme/shadows.ts +40 -0
  167. package/src/theme/spacing.ts +18 -0
  168. package/src/theme/typography.ts +35 -0
  169. package/src/utils/a11y.ts +21 -0
  170. package/svg.d.ts +7 -0
@@ -0,0 +1,158 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { Text, View, type StyleProp, type ViewStyle } from 'react-native';
3
+
4
+ import { Button, ButtonSize, ButtonVariant, IconPosition } from '../Button';
5
+ import { IconName } from '../Icon';
6
+ import { InputField, InputState, InputVariant } from '../InputField';
7
+ import { LoginShell } from '../LoginShell/LoginShell';
8
+ import { RoleCard } from '../LoginShell/RoleCard';
9
+ import {
10
+ DEFAULT_BACK_AND_SELECT_ROLE,
11
+ DEFAULT_ROLE_DESCRIPTION,
12
+ DEFAULT_ROLE_TITLE,
13
+ isValidEmail,
14
+ } from '../LoginShell/login-copy';
15
+ import { loginPageStyles as styles } from '../LoginShell/loginPageStyles';
16
+
17
+ export type LoginFormProps = {
18
+ brandingAsideAriaLabel?: string;
19
+ logoSrc?: string;
20
+ logoAlt?: string;
21
+ quoteText?: string;
22
+ quoteAttribution?: string;
23
+ backButtonLabel?: string;
24
+ roleTitle?: string;
25
+ roleDescription?: string;
26
+ pageTitle?: string;
27
+ emailLabel?: string;
28
+ emailPlaceholder?: string;
29
+ emailInitialValue?: string;
30
+ passwordLabel?: string;
31
+ passwordPlaceholder?: string;
32
+ passwordInitialValue?: string;
33
+ forgotPasswordButtonLabel?: string;
34
+ submitButtonLabel?: string;
35
+ onBack?: () => void;
36
+ onForgotPassword?: () => void;
37
+ onSubmit?: (value: { email: string; password: string }) => void;
38
+ style?: StyleProp<ViewStyle>;
39
+ };
40
+
41
+ export function LoginForm({
42
+ brandingAsideAriaLabel,
43
+ logoSrc,
44
+ logoAlt,
45
+ quoteText,
46
+ quoteAttribution,
47
+ backButtonLabel = DEFAULT_BACK_AND_SELECT_ROLE,
48
+ roleTitle = DEFAULT_ROLE_TITLE,
49
+ roleDescription = DEFAULT_ROLE_DESCRIPTION,
50
+ pageTitle = 'Sign in to your account',
51
+ emailLabel = 'Email address',
52
+ emailPlaceholder = 'you@example.com',
53
+ emailInitialValue = '',
54
+ passwordLabel = 'Password',
55
+ passwordPlaceholder = 'Enter your password',
56
+ passwordInitialValue = '',
57
+ forgotPasswordButtonLabel = 'Forgot password?',
58
+ submitButtonLabel = 'Sign in',
59
+ onBack,
60
+ onForgotPassword,
61
+ onSubmit,
62
+ style,
63
+ }: LoginFormProps) {
64
+ const [email, setEmail] = useState(emailInitialValue);
65
+ const [password, setPassword] = useState(passwordInitialValue);
66
+ const [submitted, setSubmitted] = useState(false);
67
+
68
+ useEffect(() => {
69
+ setEmail(emailInitialValue);
70
+ }, [emailInitialValue]);
71
+
72
+ useEffect(() => {
73
+ setPassword(passwordInitialValue);
74
+ }, [passwordInitialValue]);
75
+
76
+ const emailError = submitted && !isValidEmail(email) ? 'Enter a valid email address.' : '';
77
+ const passwordError = submitted && !password.trim() ? 'Enter your password.' : '';
78
+
79
+ function submit() {
80
+ setSubmitted(true);
81
+ if (!isValidEmail(email) || !password.trim()) {
82
+ return;
83
+ }
84
+ onSubmit?.({ email: email.trim(), password });
85
+ }
86
+
87
+ return (
88
+ <LoginShell
89
+ brandingAsideAriaLabel={brandingAsideAriaLabel}
90
+ logoSrc={logoSrc}
91
+ logoAlt={logoAlt}
92
+ quoteText={quoteText}
93
+ quoteAttribution={quoteAttribution}
94
+ style={style}>
95
+ <View style={styles.form}>
96
+ <View style={styles.backWrap}>
97
+ <Button
98
+ variant={ButtonVariant.LinkGray}
99
+ size={ButtonSize.Small}
100
+ iconPosition={IconPosition.Before}
101
+ iconName={IconName.ChevronLeft}
102
+ iconDecorative
103
+ label={backButtonLabel}
104
+ onPress={onBack}
105
+ />
106
+ </View>
107
+ <RoleCard title={roleTitle} description={roleDescription} />
108
+ <Text accessibilityRole="header" style={styles.pageTitle}>
109
+ {pageTitle}
110
+ </Text>
111
+ <View style={styles.fields}>
112
+ <InputField
113
+ fullWidth
114
+ variant={InputVariant.Email}
115
+ label={emailLabel}
116
+ placeholder={emailPlaceholder}
117
+ value={email}
118
+ error={emailError}
119
+ state={emailError ? InputState.Error : InputState.Default}
120
+ onValueChange={setEmail}
121
+ autoComplete="email"
122
+ inputType="email"
123
+ />
124
+ <View style={styles.passwordBlock}>
125
+ <InputField
126
+ fullWidth
127
+ fieldType="password"
128
+ label={passwordLabel}
129
+ placeholder={passwordPlaceholder}
130
+ value={password}
131
+ error={passwordError}
132
+ state={passwordError ? InputState.Error : InputState.Default}
133
+ onValueChange={setPassword}
134
+ autoComplete="password"
135
+ />
136
+ <View style={styles.forgotRow}>
137
+ <Button
138
+ variant={ButtonVariant.LinkDangerGray}
139
+ size={ButtonSize.Small}
140
+ label={forgotPasswordButtonLabel}
141
+ onPress={onForgotPassword}
142
+ />
143
+ </View>
144
+ </View>
145
+ <View style={styles.submit}>
146
+ <Button
147
+ fullWidth
148
+ variant={ButtonVariant.Primary}
149
+ size={ButtonSize.Large}
150
+ label={submitButtonLabel}
151
+ onPress={submit}
152
+ />
153
+ </View>
154
+ </View>
155
+ </View>
156
+ </LoginShell>
157
+ );
158
+ }
@@ -0,0 +1,2 @@
1
+ export { LoginForm } from './LoginForm';
2
+ export type { LoginFormProps } from './LoginForm';
@@ -0,0 +1,97 @@
1
+ import { type ReactNode } from 'react';
2
+ import {
3
+ Image,
4
+ KeyboardAvoidingView,
5
+ Platform,
6
+ ScrollView,
7
+ Text,
8
+ View,
9
+ type StyleProp,
10
+ type ViewStyle,
11
+ } from 'react-native';
12
+
13
+ import { LOGIN_HERO } from './branding-assets';
14
+ import {
15
+ DEFAULT_BRANDING_ASIDE_LABEL,
16
+ DEFAULT_LOGO_ALT,
17
+ DEFAULT_QUOTE_ATTRIBUTION,
18
+ DEFAULT_QUOTE_TEXT,
19
+ isRemoteUri,
20
+ } from './login-copy';
21
+ import { loginPageStyles as styles } from './loginPageStyles';
22
+ import { SoftechLogo } from './SoftechLogo';
23
+
24
+ export type LoginShellProps = {
25
+ brandingAsideAriaLabel?: string;
26
+ logoSrc?: string;
27
+ logoAlt?: string;
28
+ asideHeroImageSrc?: string;
29
+ asideHeroImageAlt?: string;
30
+ quoteText?: string;
31
+ quoteAttribution?: string;
32
+ showHero?: boolean;
33
+ children: ReactNode;
34
+ style?: StyleProp<ViewStyle>;
35
+ };
36
+
37
+ export function LoginShell({
38
+ brandingAsideAriaLabel = DEFAULT_BRANDING_ASIDE_LABEL,
39
+ logoSrc = '',
40
+ logoAlt = DEFAULT_LOGO_ALT,
41
+ asideHeroImageSrc = '',
42
+ asideHeroImageAlt = '',
43
+ quoteText = DEFAULT_QUOTE_TEXT,
44
+ quoteAttribution = DEFAULT_QUOTE_ATTRIBUTION,
45
+ showHero = true,
46
+ children,
47
+ style,
48
+ }: LoginShellProps) {
49
+ const remoteLogo = isRemoteUri(logoSrc);
50
+ const remoteHero = isRemoteUri(asideHeroImageSrc);
51
+ const showQuote = Boolean(quoteText.trim() || quoteAttribution.trim());
52
+
53
+ return (
54
+ <KeyboardAvoidingView
55
+ style={[styles.host, style]}
56
+ behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
57
+ <ScrollView
58
+ keyboardShouldPersistTaps="handled"
59
+ contentContainerStyle={styles.scrollContent}
60
+ showsVerticalScrollIndicator={false}>
61
+ <View accessibilityLabel={brandingAsideAriaLabel} style={styles.branding}>
62
+ {remoteLogo ? (
63
+ <Image
64
+ accessibilityLabel={logoAlt}
65
+ resizeMode="contain"
66
+ source={{ uri: logoSrc.trim() }}
67
+ style={styles.logo}
68
+ />
69
+ ) : (
70
+ <SoftechLogo accessibilityLabel={logoAlt} />
71
+ )}
72
+
73
+ {showHero ? (
74
+ <View style={styles.hero}>
75
+ <Image
76
+ accessibilityLabel={asideHeroImageAlt || undefined}
77
+ resizeMode="contain"
78
+ source={remoteHero ? { uri: asideHeroImageSrc.trim() } : LOGIN_HERO}
79
+ style={styles.heroImage}
80
+ />
81
+ </View>
82
+ ) : null}
83
+
84
+ {showQuote ? (
85
+ <View style={styles.quoteBlock}>
86
+ {quoteText.trim() ? <Text style={styles.quote}>{quoteText}</Text> : null}
87
+ {quoteAttribution.trim() ? (
88
+ <Text style={styles.quoteAttribution}>{quoteAttribution}</Text>
89
+ ) : null}
90
+ </View>
91
+ ) : null}
92
+ </View>
93
+ <View style={styles.main}>{children}</View>
94
+ </ScrollView>
95
+ </KeyboardAvoidingView>
96
+ );
97
+ }
@@ -0,0 +1,24 @@
1
+ import { Text, View } from 'react-native';
2
+
3
+ import { spacing } from '../../theme';
4
+ import { Icon, IconName } from '../Icon';
5
+ import { loginPageStyles as styles } from './loginPageStyles';
6
+
7
+ export type RoleCardProps = {
8
+ title: string;
9
+ description: string;
10
+ };
11
+
12
+ export function RoleCard({ title, description }: RoleCardProps) {
13
+ return (
14
+ <View style={styles.roleCard}>
15
+ <View accessible={false} style={styles.roleIcon}>
16
+ <Icon name={IconName.UserFrame} size={spacing['5xl']} decorative />
17
+ </View>
18
+ <View style={styles.roleText}>
19
+ <Text style={styles.roleTitle}>{title}</Text>
20
+ <Text style={styles.roleDesc}>{description}</Text>
21
+ </View>
22
+ </View>
23
+ );
24
+ }
@@ -0,0 +1,24 @@
1
+ import { Image, type ImageStyle, type StyleProp } from 'react-native';
2
+
3
+ import { DEFAULT_LOGO_ALT } from './login-copy';
4
+ import { SOFTECH_LOGO } from './branding-assets';
5
+ import { loginPageStyles as styles } from './loginPageStyles';
6
+
7
+ export type SoftechLogoProps = {
8
+ accessibilityLabel?: string;
9
+ style?: StyleProp<ImageStyle>;
10
+ };
11
+
12
+ export function SoftechLogo({
13
+ accessibilityLabel = DEFAULT_LOGO_ALT,
14
+ style,
15
+ }: SoftechLogoProps) {
16
+ return (
17
+ <Image
18
+ accessibilityLabel={accessibilityLabel}
19
+ resizeMode="contain"
20
+ source={SOFTECH_LOGO}
21
+ style={[styles.logo, style]}
22
+ />
23
+ );
24
+ }
@@ -0,0 +1,2 @@
1
+ export const SOFTECH_LOGO = require('../../assets/branding/softech-logo.png');
2
+ export const LOGIN_HERO = require('../../assets/branding/logo.jpg');
@@ -0,0 +1,20 @@
1
+ export { LoginShell } from './LoginShell';
2
+ export type { LoginShellProps } from './LoginShell';
3
+ export { SoftechLogo } from './SoftechLogo';
4
+ export type { SoftechLogoProps } from './SoftechLogo';
5
+ export { RoleCard } from './RoleCard';
6
+ export type { RoleCardProps } from './RoleCard';
7
+ export { loginPageStyles } from './loginPageStyles';
8
+ export {
9
+ DEFAULT_BACK_AND_SELECT_ROLE,
10
+ DEFAULT_BRANDING_ASIDE_LABEL,
11
+ DEFAULT_LOGO_ALT,
12
+ DEFAULT_QUOTE_ATTRIBUTION,
13
+ DEFAULT_QUOTE_TEXT,
14
+ DEFAULT_ROLE_DESCRIPTION,
15
+ DEFAULT_ROLE_TITLE,
16
+ DEFAULT_ROLES,
17
+ isRemoteUri,
18
+ isValidEmail,
19
+ } from './login-copy';
20
+ export type { LoginRoleOption } from './login-copy';
@@ -0,0 +1,45 @@
1
+ export const DEFAULT_BRANDING_ASIDE_LABEL = 'Branding';
2
+ export const DEFAULT_LOGO_ALT = 'Softech — INNOVATE. INTEGRATE. LEAD.';
3
+ export const DEFAULT_QUOTE_TEXT =
4
+ 'A business that runs on instinct will survive. A business that runs on ERP will scale.';
5
+ export const DEFAULT_QUOTE_ATTRIBUTION = '— Malcolm X';
6
+ export const DEFAULT_ROLE_TITLE = 'Super Admin';
7
+ export const DEFAULT_ROLE_DESCRIPTION = 'Oversee operations and manage users.';
8
+ export const DEFAULT_BACK_AND_SELECT_ROLE = 'Back and select role';
9
+
10
+ export type LoginRoleOption = {
11
+ id: string;
12
+ title: string;
13
+ description: string;
14
+ };
15
+
16
+ export const DEFAULT_ROLES: LoginRoleOption[] = [
17
+ {
18
+ id: 'admin',
19
+ title: 'Super Admin',
20
+ description: 'Oversee operations and manage users.',
21
+ },
22
+ {
23
+ id: 'employee',
24
+ title: 'Employee',
25
+ description: 'Complete day-to-day tasks and update records.',
26
+ },
27
+ {
28
+ id: 'manager',
29
+ title: 'Manager',
30
+ description: 'Review team work and approve requests.',
31
+ },
32
+ {
33
+ id: 'hr',
34
+ title: 'HR',
35
+ description: 'Manage employee information and tasks.',
36
+ },
37
+ ];
38
+
39
+ export function isRemoteUri(value?: string) {
40
+ return Boolean(value?.trim() && /^https?:\/\//i.test(value.trim()));
41
+ }
42
+
43
+ export function isValidEmail(value: string) {
44
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
45
+ }
@@ -0,0 +1,210 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ import { borders, colors, radius, spacing, typography } from '../../theme';
4
+
5
+ export const loginPageStyles = StyleSheet.create({
6
+ host: {
7
+ flex: 1,
8
+ width: '100%',
9
+ minHeight: '100%',
10
+ backgroundColor: colors.white,
11
+ },
12
+ scrollContent: {
13
+ flexGrow: 1,
14
+ },
15
+ branding: {
16
+ paddingTop: spacing.md,
17
+ paddingBottom: spacing.base,
18
+ paddingLeft: spacing.none,
19
+ paddingRight: spacing.base,
20
+ backgroundColor: colors.white,
21
+ borderBottomWidth: borders.width.thin,
22
+ borderBottomColor: colors.primary.light,
23
+ gap: spacing.sm,
24
+ },
25
+ logo: {
26
+ width: spacing['6xl'] * 5,
27
+ height: spacing['5xl'] + spacing.md,
28
+ maxWidth: '100%',
29
+ alignSelf: 'flex-start',
30
+ },
31
+ hero: {
32
+ width: '100%',
33
+ alignItems: 'center',
34
+ justifyContent: 'center',
35
+ paddingVertical: spacing.sm,
36
+ paddingLeft: spacing.md,
37
+ },
38
+ heroImage: {
39
+ width: '100%',
40
+ maxWidth: spacing['6xl'] * 6,
41
+ height: spacing['6xl'] * 3 + spacing.lg,
42
+ },
43
+ brandText: {
44
+ fontFamily: typography.fontFamily.base,
45
+ fontSize: typography.fontSize.md,
46
+ fontWeight: typography.fontWeight.bold,
47
+ color: colors.text.strong,
48
+ },
49
+ quoteBlock: {
50
+ width: '100%',
51
+ paddingHorizontal: spacing.base,
52
+ },
53
+ quote: {
54
+ fontFamily: typography.fontFamily.base,
55
+ fontSize: typography.fontSize.sm,
56
+ fontStyle: 'italic',
57
+ textAlign: 'center',
58
+ color: colors.text.muted,
59
+ },
60
+ quoteAttribution: {
61
+ marginTop: spacing.xs,
62
+ fontFamily: typography.fontFamily.base,
63
+ fontSize: typography.fontSize.sm,
64
+ fontStyle: 'normal',
65
+ fontWeight: typography.fontWeight.medium,
66
+ textAlign: 'center',
67
+ color: colors.text.strong,
68
+ },
69
+ main: {
70
+ flexGrow: 1,
71
+ justifyContent: 'center',
72
+ backgroundColor: colors.primary.lightest,
73
+ paddingHorizontal: spacing.base,
74
+ paddingTop: spacing['2xl'],
75
+ paddingBottom: spacing['3xl'],
76
+ },
77
+ form: {
78
+ width: '100%',
79
+ maxWidth: spacing['6xl'] * 8,
80
+ alignSelf: 'center',
81
+ gap: spacing.md,
82
+ },
83
+ backWrap: {
84
+ alignSelf: 'flex-start',
85
+ },
86
+ roleCard: {
87
+ flexDirection: 'row',
88
+ alignItems: 'center',
89
+ gap: spacing.sm,
90
+ width: '100%',
91
+ paddingVertical: spacing.sm,
92
+ paddingHorizontal: spacing.md,
93
+ borderWidth: borders.width.thin,
94
+ borderColor: colors.login.roleCardBorder,
95
+ borderRadius: radius.md,
96
+ backgroundColor: colors.primary.lightest,
97
+ },
98
+ roleIcon: {
99
+ width: spacing['5xl'],
100
+ height: spacing['5xl'],
101
+ alignItems: 'center',
102
+ justifyContent: 'center',
103
+ },
104
+ roleText: {
105
+ flex: 1,
106
+ minWidth: 0,
107
+ gap: spacing.xs,
108
+ },
109
+ roleTitle: {
110
+ fontFamily: typography.fontFamily.base,
111
+ fontSize: typography.fontSize.sm,
112
+ fontWeight: typography.fontWeight.semibold,
113
+ color: colors.text.strong,
114
+ },
115
+ roleDesc: {
116
+ fontFamily: typography.fontFamily.base,
117
+ fontSize: typography.fontSize.sm,
118
+ color: colors.text.muted,
119
+ },
120
+ pageTitle: {
121
+ marginTop: spacing.xs,
122
+ fontFamily: typography.fontFamily.base,
123
+ fontSize: typography.fontSize.xl,
124
+ fontWeight: typography.fontWeight.bold,
125
+ color: colors.text.strong,
126
+ },
127
+ pageTitleVerify: {
128
+ marginTop: spacing.lg,
129
+ },
130
+ fields: {
131
+ width: '100%',
132
+ gap: spacing.md,
133
+ marginTop: spacing.xs,
134
+ },
135
+ passwordBlock: {
136
+ width: '100%',
137
+ gap: spacing.sm,
138
+ },
139
+ forgotRow: {
140
+ width: '100%',
141
+ alignItems: 'flex-end',
142
+ },
143
+ submit: {
144
+ marginTop: spacing.sm,
145
+ },
146
+ inlineRow: {
147
+ flexDirection: 'row',
148
+ flexWrap: 'wrap',
149
+ alignItems: 'center',
150
+ gap: spacing.xs,
151
+ },
152
+ inlineCentered: {
153
+ justifyContent: 'center',
154
+ marginTop: spacing.xs,
155
+ },
156
+ inlinePrefix: {
157
+ fontFamily: typography.fontFamily.base,
158
+ fontSize: typography.fontSize.sm,
159
+ color: colors.text.strong,
160
+ },
161
+ roleList: {
162
+ width: '100%',
163
+ gap: spacing.md,
164
+ },
165
+ roleOption: {
166
+ width: '100%',
167
+ flexDirection: 'row',
168
+ alignItems: 'center',
169
+ gap: spacing.md,
170
+ paddingVertical: spacing.md,
171
+ paddingHorizontal: spacing.md,
172
+ borderWidth: borders.width.thin,
173
+ borderColor: colors.login.roleCardBorder,
174
+ borderRadius: radius.md,
175
+ backgroundColor: colors.white,
176
+ overflow: 'hidden',
177
+ },
178
+ roleOptionIconWrap: {
179
+ width: spacing['5xl'] + spacing.base,
180
+ height: spacing['5xl'] + spacing.base,
181
+ alignItems: 'center',
182
+ justifyContent: 'center',
183
+ borderRadius: radius.sm,
184
+ backgroundColor: colors.primary.lightest,
185
+ },
186
+ roleOptionIconInner: {
187
+ width: spacing['4xl'] + spacing.sm,
188
+ height: spacing['4xl'] + spacing.sm,
189
+ alignItems: 'center',
190
+ justifyContent: 'center',
191
+ borderRadius: radius.full,
192
+ backgroundColor: colors.white,
193
+ },
194
+ roleOptionText: {
195
+ flex: 1,
196
+ minWidth: 0,
197
+ gap: spacing.xs,
198
+ },
199
+ roleOptionTitle: {
200
+ fontFamily: typography.fontFamily.base,
201
+ fontSize: typography.fontSize.base,
202
+ fontWeight: typography.fontWeight.bold,
203
+ color: colors.text.strong,
204
+ },
205
+ roleOptionDesc: {
206
+ fontFamily: typography.fontFamily.base,
207
+ fontSize: typography.fontSize.sm,
208
+ color: colors.text.muted,
209
+ },
210
+ });