@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,336 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import {
3
+ Platform,
4
+ Pressable,
5
+ StyleSheet,
6
+ View,
7
+ type StyleProp,
8
+ type ViewStyle,
9
+ } from 'react-native';
10
+
11
+ import { borders, button as buttonTokens, colors, radius, shadows, spacing, typography } from '../../theme';
12
+ import { Icon, IconName } from '../Icon';
13
+ import { Label } from '../Label';
14
+
15
+ export const CheckboxSize = {
16
+ Small: 'sm',
17
+ Medium: 'md',
18
+ Large: 'lg',
19
+ } as const;
20
+
21
+ export type CheckboxSize = (typeof CheckboxSize)[keyof typeof CheckboxSize];
22
+
23
+ export const CheckboxShape = {
24
+ Square: 'square',
25
+ Circle: 'circle',
26
+ } as const;
27
+
28
+ export type CheckboxShape = (typeof CheckboxShape)[keyof typeof CheckboxShape];
29
+
30
+ export const CheckboxState = {
31
+ Default: 'default',
32
+ Hover: 'hover',
33
+ Focused: 'focused',
34
+ Disabled: 'disabled',
35
+ } as const;
36
+
37
+ export type CheckboxState = (typeof CheckboxState)[keyof typeof CheckboxState];
38
+
39
+ export type CheckboxProps = {
40
+ checked?: boolean;
41
+ indeterminate?: boolean;
42
+ disabled?: boolean;
43
+ state?: CheckboxState;
44
+ size?: CheckboxSize;
45
+ shape?: CheckboxShape;
46
+ filled?: boolean;
47
+ label?: string;
48
+ supportingText?: string;
49
+ required?: boolean;
50
+ inputId?: string;
51
+ accessibilityLabel?: string;
52
+ onCheckedChange?: (checked: boolean) => void;
53
+ onIndeterminateChange?: (indeterminate: boolean) => void;
54
+ style?: StyleProp<ViewStyle>;
55
+ };
56
+
57
+ const isNative = Platform.OS !== 'web';
58
+
59
+ const BOX_SIZE = {
60
+ [CheckboxSize.Small]: spacing.base,
61
+ [CheckboxSize.Medium]: spacing.lg,
62
+ [CheckboxSize.Large]: spacing.xl,
63
+ } as const;
64
+
65
+ const ICON_SIZE = {
66
+ [CheckboxSize.Small]: spacing.md,
67
+ [CheckboxSize.Medium]: spacing.base,
68
+ [CheckboxSize.Large]: spacing.lg,
69
+ } as const;
70
+
71
+ function containsNode(host: unknown, target: EventTarget | null) {
72
+ if (!host || !target || typeof host !== 'object') {
73
+ return false;
74
+ }
75
+ const node = host as { contains?: (other: EventTarget) => boolean };
76
+ return typeof node.contains === 'function' ? node.contains(target) : false;
77
+ }
78
+
79
+ function hitSlopFor(boxSize: number) {
80
+ const extra = Math.max(spacing.none, (buttonTokens.minTouch - boxSize) / 2);
81
+ if (extra === spacing.none) {
82
+ return undefined;
83
+ }
84
+ return { top: extra, bottom: extra, left: extra, right: extra };
85
+ }
86
+
87
+ function webRing(): ViewStyle {
88
+ return {
89
+ boxShadow: `0 0 0 ${borders.width.thick}px ${colors.checkbox.shadowRing}, 0 ${shadows.boxLight.offsetY}px ${shadows.boxLight.radius}px ${colors.checkbox.shadowElevation}`,
90
+ } as ViewStyle;
91
+ }
92
+
93
+ function nativeRingStyle(isCircle: boolean): ViewStyle {
94
+ return {
95
+ position: 'absolute',
96
+ top: -borders.width.thick,
97
+ right: -borders.width.thick,
98
+ bottom: -borders.width.thick,
99
+ left: -borders.width.thick,
100
+ borderRadius: isCircle ? radius.full : radius.sm + borders.width.thick,
101
+ borderWidth: borders.width.thick,
102
+ borderColor: colors.checkbox.shadowRing,
103
+ zIndex: 0,
104
+ };
105
+ }
106
+
107
+ export function Checkbox({
108
+ checked = false,
109
+ indeterminate = false,
110
+ disabled = false,
111
+ state = CheckboxState.Default,
112
+ size = CheckboxSize.Medium,
113
+ shape = CheckboxShape.Square,
114
+ filled = false,
115
+ label = '',
116
+ supportingText = '',
117
+ required = false,
118
+ inputId,
119
+ accessibilityLabel,
120
+ onCheckedChange,
121
+ onIndeterminateChange,
122
+ style,
123
+ }: CheckboxProps) {
124
+ const hostRef = useRef<View>(null);
125
+ const [internalChecked, setInternalChecked] = useState(checked);
126
+ const [internalIndeterminate, setInternalIndeterminate] = useState(indeterminate);
127
+ const [focused, setFocused] = useState(false);
128
+ const [hovered, setHovered] = useState(false);
129
+
130
+ useEffect(() => {
131
+ setInternalChecked(checked);
132
+ }, [checked]);
133
+
134
+ useEffect(() => {
135
+ setInternalIndeterminate(indeterminate);
136
+ }, [indeterminate]);
137
+
138
+ const isDisabled = disabled || state === CheckboxState.Disabled;
139
+ const isChecked = internalChecked;
140
+ const isIndeterminate = internalIndeterminate;
141
+ const isOn = isChecked || isIndeterminate;
142
+ const isCircle = shape === CheckboxShape.Circle;
143
+ const isFilledCircle = isCircle && filled;
144
+ const hasText = Boolean(label) || Boolean(supportingText?.trim());
145
+ const hasSupporting = Boolean(supportingText?.trim());
146
+ const showHover = !isDisabled && (state === CheckboxState.Hover || hovered);
147
+ const showFocus = !isDisabled && (state === CheckboxState.Focused || (!isNative && focused));
148
+ const showRing = !isDisabled && (showHover || showFocus);
149
+ const boxSize = BOX_SIZE[size];
150
+ const iconSize = ICON_SIZE[size];
151
+
152
+ let backgroundColor: string = colors.checkbox.bgDefault;
153
+ let borderColor: string = colors.checkbox.borderDefault;
154
+
155
+ if (isDisabled) {
156
+ backgroundColor = colors.checkbox.disabledBg;
157
+ borderColor = colors.checkbox.disabledBorder;
158
+ } else if (isFilledCircle) {
159
+ backgroundColor = colors.checkbox.bgDefault;
160
+ borderColor = colors.checkbox.borderActive;
161
+ } else if (isOn || showHover) {
162
+ backgroundColor = colors.checkbox.bgActive;
163
+ borderColor = colors.checkbox.borderActive;
164
+ } else if (showFocus) {
165
+ backgroundColor = colors.checkbox.bgDefault;
166
+ borderColor = colors.checkbox.borderActive;
167
+ }
168
+
169
+ const iconName = isIndeterminate && !isCircle
170
+ ? IconName.CheckboxMinus
171
+ : isChecked && isCircle
172
+ ? IconName.RadioDot
173
+ : isChecked && !isCircle
174
+ ? IconName.Checkmark
175
+ : '';
176
+
177
+ const toggle = () => {
178
+ if (isDisabled) {
179
+ return;
180
+ }
181
+
182
+ if (isIndeterminate) {
183
+ setInternalIndeterminate(false);
184
+ setInternalChecked(true);
185
+ onIndeterminateChange?.(false);
186
+ onCheckedChange?.(true);
187
+ return;
188
+ }
189
+
190
+ const next = !isChecked;
191
+ setInternalChecked(next);
192
+ onCheckedChange?.(next);
193
+ };
194
+
195
+ useEffect(() => {
196
+ if (Platform.OS !== 'web' || !focused) {
197
+ return;
198
+ }
199
+
200
+ const doc = globalThis.document as Document | undefined;
201
+ if (!doc) {
202
+ return;
203
+ }
204
+
205
+ const onPointerDown = (event: Event) => {
206
+ if (!containsNode(hostRef.current, event.target)) {
207
+ setFocused(false);
208
+ }
209
+ };
210
+
211
+ doc.addEventListener('mousedown', onPointerDown);
212
+ doc.addEventListener('touchstart', onPointerDown);
213
+ return () => {
214
+ doc.removeEventListener('mousedown', onPointerDown);
215
+ doc.removeEventListener('touchstart', onPointerDown);
216
+ };
217
+ }, [focused]);
218
+
219
+ return (
220
+ <Pressable
221
+ ref={hostRef}
222
+ accessibilityRole="checkbox"
223
+ accessibilityState={{ checked: isIndeterminate ? 'mixed' : isChecked, disabled: isDisabled }}
224
+ accessibilityLabel={accessibilityLabel || label || supportingText || undefined}
225
+ disabled={isDisabled}
226
+ nativeID={inputId}
227
+ hitSlop={hasText ? undefined : hitSlopFor(boxSize)}
228
+ onHoverIn={() => setHovered(true)}
229
+ onHoverOut={() => setHovered(false)}
230
+ onFocus={() => setFocused(true)}
231
+ onBlur={() => setFocused(false)}
232
+ onPress={() => {
233
+ toggle();
234
+ setFocused(false);
235
+ }}
236
+ style={[
237
+ styles.wrapper,
238
+ styles.pressableReset,
239
+ hasText && styles.wrapperWithLabel,
240
+ hasSupporting && styles.wrapperWithSupporting,
241
+ isDisabled && styles.wrapperDisabled,
242
+ style,
243
+ ]}>
244
+ <View style={styles.boxHost}>
245
+ {showRing && isNative ? <View pointerEvents="none" style={nativeRingStyle(isCircle)} /> : null}
246
+ <View
247
+ style={[
248
+ styles.box,
249
+ {
250
+ width: boxSize,
251
+ height: boxSize,
252
+ borderRadius: isCircle ? radius.full : radius.sm,
253
+ backgroundColor,
254
+ borderColor,
255
+ },
256
+ showRing && !isNative && webRing(),
257
+ ]}>
258
+ {iconName ? (
259
+ <Icon
260
+ name={iconName}
261
+ size={iconSize}
262
+ color={isDisabled ? colors.checkbox.disabledIcon : colors.checkbox.icon}
263
+ decorative
264
+ />
265
+ ) : null}
266
+ </View>
267
+ </View>
268
+
269
+ {hasText ? (
270
+ <Label
271
+ embedded
272
+ text={label}
273
+ supportingText={supportingText}
274
+ required={required}
275
+ htmlFor={inputId}
276
+ style={styles.text}
277
+ labelStyle={[styles.label, isDisabled && styles.labelDisabled]}
278
+ supportingStyle={[styles.description, isDisabled && styles.descriptionDisabled]}
279
+ />
280
+ ) : null}
281
+ </Pressable>
282
+ );
283
+ }
284
+
285
+ const styles = StyleSheet.create({
286
+ wrapper: {
287
+ flexDirection: 'row',
288
+ alignItems: 'center',
289
+ alignSelf: 'flex-start',
290
+ maxWidth: '100%',
291
+ },
292
+ pressableReset: {
293
+ outlineWidth: 0,
294
+ outlineStyle: 'solid',
295
+ outlineColor: colors.transparent,
296
+ outlineOffset: 0,
297
+ },
298
+ wrapperWithLabel: {
299
+ gap: spacing.md,
300
+ },
301
+ wrapperWithSupporting: {
302
+ alignItems: 'flex-start',
303
+ },
304
+ wrapperDisabled: {
305
+ opacity: 1,
306
+ },
307
+ boxHost: {
308
+ position: 'relative',
309
+ overflow: 'visible',
310
+ flexShrink: 0,
311
+ },
312
+ box: {
313
+ borderWidth: borders.width.thin,
314
+ alignItems: 'center',
315
+ justifyContent: 'center',
316
+ overflow: 'visible',
317
+ },
318
+ text: {
319
+ flexShrink: 1,
320
+ minWidth: spacing.none,
321
+ },
322
+ label: {
323
+ color: colors.checkbox.label,
324
+ fontWeight: typography.fontWeight.medium,
325
+ },
326
+ labelDisabled: {
327
+ color: colors.checkbox.labelDisabled,
328
+ },
329
+ description: {
330
+ color: colors.checkbox.description,
331
+ fontWeight: typography.fontWeight.normal,
332
+ },
333
+ descriptionDisabled: {
334
+ color: colors.checkbox.descriptionDisabled,
335
+ },
336
+ });
@@ -0,0 +1,2 @@
1
+ export { Checkbox, CheckboxSize, CheckboxShape, CheckboxState } from './Checkbox';
2
+ export type { CheckboxProps } from './Checkbox';
@@ -0,0 +1,161 @@
1
+ import { 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 } 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
+ } from '../LoginShell/login-copy';
14
+ import { loginPageStyles as styles } from '../LoginShell/loginPageStyles';
15
+
16
+ export type CreatePasswordProps = {
17
+ brandingAsideAriaLabel?: string;
18
+ logoSrc?: string;
19
+ logoAlt?: string;
20
+ quoteText?: string;
21
+ quoteAttribution?: string;
22
+ backButtonLabel?: string;
23
+ roleTitle?: string;
24
+ roleDescription?: string;
25
+ pageTitle?: string;
26
+ newPasswordLabel?: string;
27
+ newPasswordPlaceholder?: string;
28
+ newPasswordHint?: string;
29
+ confirmPasswordLabel?: string;
30
+ confirmPasswordPlaceholder?: string;
31
+ confirmPasswordHint?: string;
32
+ submitButtonLabel?: string;
33
+ signUpPromptText?: string;
34
+ signUpButtonLabel?: string;
35
+ minLengthPasswordError?: string;
36
+ passwordMismatchError?: string;
37
+ onBack?: () => void;
38
+ onSignUp?: () => void;
39
+ onSubmit?: (value: { newPassword: string; confirmPassword: string }) => void;
40
+ style?: StyleProp<ViewStyle>;
41
+ };
42
+
43
+ export function CreatePassword({
44
+ brandingAsideAriaLabel,
45
+ logoSrc,
46
+ logoAlt,
47
+ quoteText,
48
+ quoteAttribution,
49
+ backButtonLabel = DEFAULT_BACK_AND_SELECT_ROLE,
50
+ roleTitle = DEFAULT_ROLE_TITLE,
51
+ roleDescription = DEFAULT_ROLE_DESCRIPTION,
52
+ pageTitle = 'Create a new Password',
53
+ newPasswordLabel = 'Enter your New Password',
54
+ newPasswordPlaceholder = 'Enter your new password',
55
+ newPasswordHint = '',
56
+ confirmPasswordLabel = 'Confirm Password',
57
+ confirmPasswordPlaceholder = 'Johnson7845',
58
+ confirmPasswordHint = '',
59
+ submitButtonLabel = 'Submit',
60
+ signUpPromptText = "Don't you have an account?",
61
+ signUpButtonLabel = 'Sign up',
62
+ minLengthPasswordError = 'Use at least 8 characters.',
63
+ passwordMismatchError = 'Passwords do not match.',
64
+ onBack,
65
+ onSignUp,
66
+ onSubmit,
67
+ style,
68
+ }: CreatePasswordProps) {
69
+ const [newPassword, setNewPassword] = useState('');
70
+ const [confirmPassword, setConfirmPassword] = useState('');
71
+ const [submitted, setSubmitted] = useState(false);
72
+
73
+ const newPasswordError =
74
+ submitted && newPassword.length < 8 ? minLengthPasswordError : '';
75
+ const confirmError =
76
+ submitted && confirmPassword && confirmPassword !== newPassword
77
+ ? passwordMismatchError
78
+ : submitted && !confirmPassword.trim()
79
+ ? passwordMismatchError
80
+ : '';
81
+
82
+ function submit() {
83
+ setSubmitted(true);
84
+ if (newPassword.length < 8 || !confirmPassword.trim() || confirmPassword !== newPassword) {
85
+ return;
86
+ }
87
+ onSubmit?.({ newPassword, confirmPassword });
88
+ }
89
+
90
+ return (
91
+ <LoginShell
92
+ brandingAsideAriaLabel={brandingAsideAriaLabel}
93
+ logoSrc={logoSrc}
94
+ logoAlt={logoAlt}
95
+ quoteText={quoteText}
96
+ quoteAttribution={quoteAttribution}
97
+ style={style}>
98
+ <View style={styles.form}>
99
+ <View style={styles.backWrap}>
100
+ <Button
101
+ variant={ButtonVariant.LinkGray}
102
+ size={ButtonSize.Small}
103
+ iconPosition={IconPosition.Before}
104
+ iconName={IconName.ChevronLeft}
105
+ iconDecorative
106
+ label={backButtonLabel}
107
+ onPress={onBack}
108
+ />
109
+ </View>
110
+ <RoleCard title={roleTitle} description={roleDescription} />
111
+ <Text accessibilityRole="header" style={[styles.pageTitle, styles.pageTitleVerify]}>
112
+ {pageTitle}
113
+ </Text>
114
+ <View style={styles.fields}>
115
+ <InputField
116
+ fullWidth
117
+ fieldType="password"
118
+ label={newPasswordLabel}
119
+ placeholder={newPasswordPlaceholder}
120
+ hint={newPasswordError ? '' : newPasswordHint}
121
+ value={newPassword}
122
+ error={newPasswordError}
123
+ state={newPasswordError ? InputState.Error : InputState.Default}
124
+ onValueChange={setNewPassword}
125
+ autoComplete="password"
126
+ />
127
+ <InputField
128
+ fullWidth
129
+ fieldType="password"
130
+ label={confirmPasswordLabel}
131
+ placeholder={confirmPasswordPlaceholder}
132
+ hint={confirmError ? '' : confirmPasswordHint}
133
+ value={confirmPassword}
134
+ error={confirmError}
135
+ state={confirmError ? InputState.Error : InputState.Default}
136
+ onValueChange={setConfirmPassword}
137
+ autoComplete="password"
138
+ />
139
+ <View style={styles.submit}>
140
+ <Button
141
+ fullWidth
142
+ variant={ButtonVariant.Primary}
143
+ size={ButtonSize.Large}
144
+ label={submitButtonLabel}
145
+ onPress={submit}
146
+ />
147
+ </View>
148
+ <View style={[styles.inlineRow, styles.inlineCentered]}>
149
+ <Text style={styles.inlinePrefix}>{signUpPromptText}</Text>
150
+ <Button
151
+ variant={ButtonVariant.LinkPrimary}
152
+ size={ButtonSize.Small}
153
+ label={signUpButtonLabel}
154
+ onPress={onSignUp}
155
+ />
156
+ </View>
157
+ </View>
158
+ </View>
159
+ </LoginShell>
160
+ );
161
+ }
@@ -0,0 +1,2 @@
1
+ export { CreatePassword } from './CreatePassword';
2
+ export type { CreatePasswordProps } from './CreatePassword';